/* * Copyright (C) 2019 Rockchip Electronics Co., Ltd. * author: Zhihua Wang, hogan.wang@rock-chips.com * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL), available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "vpu_encode.h" #include #include #include int vpu_encode_jpeg_init(struct vpu_encode* encode, int width, int height, int quant, MppFrameFormat format) { MPP_RET ret = MPP_OK; MppEncCfg cfg; MppCodingType type = MPP_VIDEO_CodingMJPEG; MppFrameFormat fmt = format; memset(encode, 0, sizeof(*encode)); encode->width = width; encode->height = height; encode->enc_out_data = NULL; encode->enc_out_length = 0; ret = mpp_create(&encode->mpp_ctx, &encode->mpi); if (MPP_OK != ret) { printf("mpp_create failed\n"); return -1; } MppApi* mpi = encode->mpi; MppCtx mpp_ctx = encode->mpp_ctx; ret = mpp_init(mpp_ctx, MPP_CTX_ENC, type); if (MPP_OK != ret) { printf("mpp_init failed\n"); return -1; } ret = mpp_enc_cfg_init(&cfg); if (ret || !cfg) { printf("mpp_enc_cfg_init failed ret %d\n", ret); return -1; } mpp_enc_cfg_set_s32(cfg, "prep:width", width); mpp_enc_cfg_set_s32(cfg, "prep:height", height); mpp_enc_cfg_set_s32(cfg, "prep:hor_stride", width); mpp_enc_cfg_set_s32(cfg, "prep:ver_stride", height); mpp_enc_cfg_set_s32(cfg, "prep:format", fmt); mpp_enc_cfg_set_s32(cfg, "rc:mode", MPP_ENC_RC_MODE_FIXQP); mpp_enc_cfg_set_s32(cfg, "jpeg:quant", quant); /* range 0 - 10, worst -> best */ ret = mpi->control(mpp_ctx, MPP_ENC_SET_CFG, cfg); if (ret) { printf("mpi control MPP_ENC_SET_CFG failed ret %d\n", ret); mpp_enc_cfg_deinit(cfg); return -1; } mpp_enc_cfg_deinit(cfg); return 0; } int vpu_encode_jpeg_doing(struct vpu_encode* encode, void* srcbuf, int src_fd, size_t src_size, void *dst_buf, int dst_fd, size_t dst_size) { MPP_RET ret = MPP_OK; RK_U32 width = encode->width; RK_U32 height = encode->height; MppCtx mpp_ctx = encode->mpp_ctx; MppApi* mpi = encode->mpi; MppTask task = NULL; MppFrame frame = NULL; MppBuffer pic_buf = NULL; MppBuffer str_buf = NULL; MppBufferGroup memGroup = NULL; encode->enc_out_data = NULL; encode->enc_out_length = 0; ret = mpp_frame_init(&frame); if (MPP_OK != ret) { printf("mpp_frame_init failed\n"); goto ENCODE_OUT; } mpp_frame_set_width(frame, width); mpp_frame_set_height(frame, height); mpp_frame_set_hor_stride(frame, width); mpp_frame_set_ver_stride(frame, height); mpp_frame_set_eos(frame, 1); if (src_fd > 0) { MppBufferInfo inputCommit; memset(&inputCommit, 0, sizeof(inputCommit)); inputCommit.type = MPP_BUFFER_TYPE_ION; inputCommit.size = src_size; inputCommit.fd = src_fd; ret = mpp_buffer_import(&pic_buf, &inputCommit); if (ret) { printf("import input picture buffer failed\n"); goto ENCODE_OUT; } } else { if (NULL == srcbuf) { ret = MPP_ERR_NULL_PTR; goto ENCODE_OUT; } ret = mpp_buffer_get(memGroup, &pic_buf, src_size); if (ret) { printf("allocate input picture buffer failed\n"); goto ENCODE_OUT; } memcpy((RK_U8*)mpp_buffer_get_ptr(pic_buf), srcbuf, src_size); } if (dst_fd > 0) { MppBufferInfo outputCommit; memset(&outputCommit, 0, sizeof(outputCommit)); outputCommit.type = MPP_BUFFER_TYPE_ION; outputCommit.fd = dst_fd; outputCommit.size = dst_size; outputCommit.ptr = dst_buf; ret = mpp_buffer_import(&str_buf, &outputCommit); if (ret) { printf("import output stream buffer failed\n"); goto ENCODE_OUT; } } else { printf("output stream buffer error\n"); goto ENCODE_OUT; } mpp_frame_set_buffer(frame, pic_buf); if (encode->packet) mpp_packet_deinit(&encode->packet); mpp_packet_init_with_buffer(&encode->packet, str_buf); mpp_packet_set_length(encode->packet, 0); //mpp_log_f("mpp import input fd %d output fd %d", mpp_buffer_get_fd(pic_buf), // mpp_buffer_get_fd(str_buf)); ret = mpi->poll(mpp_ctx, MPP_PORT_INPUT, MPP_POLL_BLOCK); if (ret) { printf("mpp task input poll failed ret %d\n", ret); goto ENCODE_OUT; } ret = mpi->dequeue(mpp_ctx, MPP_PORT_INPUT, &task); if (ret || NULL == task) { printf("mpp task input dequeue failed ret %d task %p\n", ret, task); goto ENCODE_OUT; } mpp_task_meta_set_frame(task, KEY_INPUT_FRAME, frame); mpp_task_meta_set_packet(task, KEY_OUTPUT_PACKET, encode->packet); ret = mpi->enqueue(mpp_ctx, MPP_PORT_INPUT, task); if (ret) { printf("mpp task input enqueue failed\n"); goto ENCODE_OUT; } ret = mpi->poll(mpp_ctx, MPP_PORT_OUTPUT, MPP_POLL_BLOCK); if (ret) { printf("mpp task output poll failed ret %d\n", ret); goto ENCODE_OUT; } ret = mpi->dequeue(mpp_ctx, MPP_PORT_OUTPUT, &task); if (ret || NULL == task) { printf("mpp task output dequeue failed ret %d task %p\n", ret, task); goto ENCODE_OUT; } if (task) { MppFrame packet_out = NULL; mpp_task_meta_get_packet(task, KEY_OUTPUT_PACKET, &packet_out); assert(packet_out == encode->packet); ret = mpi->enqueue(mpp_ctx, MPP_PORT_OUTPUT, task); if (ret) { printf("mpp task output enqueue failed\n"); goto ENCODE_OUT; } task = NULL; } if ((encode->packet != NULL)) { size_t length = mpp_packet_get_length(encode->packet); encode->enc_out_data = dst_buf; encode->enc_out_length = length; } ret = mpi->reset(mpp_ctx); if (MPP_OK != ret) { printf("mpi->reset failed\n"); goto ENCODE_OUT; } ENCODE_OUT: if (pic_buf) { mpp_buffer_put(pic_buf); pic_buf = NULL; } if (str_buf) { mpp_buffer_put(str_buf); str_buf = NULL; } if (frame) mpp_frame_deinit(&frame); return ret; } void vpu_encode_jpeg_done(struct vpu_encode* encode) { if (encode) { if (encode->packet) mpp_packet_deinit(&encode->packet); if (encode->mpp_ctx) { mpp_destroy(encode->mpp_ctx); encode->mpp_ctx = NULL; } } }