gboolean gst_imx_vpu_encoder_load() { gboolean ret; g_mutex_lock(&load_mutex); imx_vpu_setup_heap_allocator_functions(); ret = (imx_vpu_enc_load() == IMX_VPU_ENC_RETURN_CODE_OK); g_mutex_unlock(&load_mutex); return ret; }
ImxVpuEncReturnCodes imx_vpu_jpeg_enc_open(ImxVpuJPEGEncoder **jpeg_encoder, ImxVpuDMABufferAllocator *dma_buffer_allocator) { ImxVpuEncReturnCodes ret = IMX_VPU_ENC_RETURN_CODE_OK; ImxVpuJPEGEncoder *jpegenc = NULL; assert(jpeg_encoder != NULL); if ((ret = imx_vpu_enc_load()) != IMX_VPU_ENC_RETURN_CODE_OK) goto error; jpegenc = IMX_VPU_ALLOC(sizeof(ImxVpuJPEGEncoder)); if (jpegenc == NULL) { IMX_VPU_ERROR("allocating memory for JPEG encoder object failed"); ret = IMX_VPU_ENC_RETURN_CODE_ERROR; goto error; } memset(jpegenc, 0, sizeof(ImxVpuJPEGEncoder)); jpegenc->dma_buffer_allocator = (dma_buffer_allocator != NULL) ? dma_buffer_allocator : imx_vpu_enc_get_default_allocator(); imx_vpu_enc_get_bitstream_buffer_info(&(jpegenc->bitstream_buffer_size), &(jpegenc->bitstream_buffer_alignment)); jpegenc->bitstream_buffer = imx_vpu_dma_buffer_allocate(jpegenc->dma_buffer_allocator, jpegenc->bitstream_buffer_size, jpegenc->bitstream_buffer_alignment, 0); if (jpegenc->bitstream_buffer == NULL) { IMX_VPU_ERROR("could not allocate DMA buffer for bitstream buffer with %u bytes and alignment %u", jpegenc->bitstream_buffer_size, jpegenc->bitstream_buffer_alignment); ret = IMX_VPU_ENC_RETURN_CODE_ERROR; goto error; } /* imx_vpu_enc_open() is called later on demand during encoding, to accomodate * for potentially changing parameters like width, height, quality factor */ *jpeg_encoder = jpegenc; return IMX_VPU_ENC_RETURN_CODE_OK; error: if ((jpegenc != NULL) && (jpegenc->bitstream_buffer != NULL)) imx_vpu_dma_buffer_deallocate(jpegenc->bitstream_buffer); return ret; }
Context* init(FILE *input_file, FILE *output_file) { Context *ctx; ImxVpuEncOpenParams open_params; unsigned int i; ctx = calloc(1, sizeof(Context)); ctx->fin = input_file; ctx->fout = output_file; /* Set the open params. Use the default values (note that memset must still * be called to ensure all values are set to 0 initially; the * imx_vpu_enc_set_default_open_params() function does not do this!). * Then, set a bitrate of 0 kbps, which tells the VPU to use constant quality * mode instead (controlled by the quant_param field in ImxVpuEncParams). * Frame width & height are also necessary, as are the frame rate numerator * and denominator. */ memset(&open_params, 0, sizeof(open_params)); imx_vpu_enc_set_default_open_params(IMX_VPU_CODEC_FORMAT_H264, &open_params); open_params.bitrate = 0; open_params.frame_width = FRAME_WIDTH; open_params.frame_height = FRAME_HEIGHT; open_params.frame_rate_numerator = FPS_N; open_params.frame_rate_denominator = FPS_D; /* Load the VPU firmware */ imx_vpu_enc_load(); /* Retrieve information about the required bitstream buffer and allocate one based on this */ imx_vpu_enc_get_bitstream_buffer_info(&(ctx->bitstream_buffer_size), &(ctx->bitstream_buffer_alignment)); ctx->bitstream_buffer = imx_vpu_dma_buffer_allocate( imx_vpu_enc_get_default_allocator(), ctx->bitstream_buffer_size, ctx->bitstream_buffer_alignment, 0 ); /* Open an encoder instance, using the previously allocated bitstream buffer */ imx_vpu_enc_open(&(ctx->vpuenc), &open_params, ctx->bitstream_buffer); /* Retrieve the initial information to allocate framebuffers for the * encoding process (unlike with decoding, these framebuffers are used * only internally by the encoder as temporary storage; encoded data * doesn't go in there, nor do raw input frames) */ imx_vpu_enc_get_initial_info(ctx->vpuenc, &(ctx->initial_info)); ctx->num_framebuffers = ctx->initial_info.min_num_required_framebuffers; fprintf(stderr, "num framebuffers: %u\n", ctx->num_framebuffers); /* Using the initial information, calculate appropriate framebuffer sizes */ imx_vpu_calc_framebuffer_sizes(COLOR_FORMAT, FRAME_WIDTH, FRAME_HEIGHT, ctx->initial_info.framebuffer_alignment, 0, 0, &(ctx->calculated_sizes)); fprintf( stderr, "calculated sizes: frame width&height: %dx%d Y stride: %u CbCr stride: %u Y size: %u CbCr size: %u MvCol size: %u total size: %u\n", ctx->calculated_sizes.aligned_frame_width, ctx->calculated_sizes.aligned_frame_height, ctx->calculated_sizes.y_stride, ctx->calculated_sizes.cbcr_stride, ctx->calculated_sizes.y_size, ctx->calculated_sizes.cbcr_size, ctx->calculated_sizes.mvcol_size, ctx->calculated_sizes.total_size ); /* Allocate memory blocks for the framebuffer and DMA buffer structures, * and allocate the DMA buffers themselves */ ctx->framebuffers = malloc(sizeof(ImxVpuFramebuffer) * ctx->num_framebuffers); ctx->fb_dmabuffers = malloc(sizeof(ImxVpuDMABuffer*) * ctx->num_framebuffers); for (i = 0; i < ctx->num_framebuffers; ++i) { /* Allocate a DMA buffer for each framebuffer. It is possible to specify alternate allocators; * all that is required is that the allocator provides physically contiguous memory * (necessary for DMA transfers) and respecs the alignment value. */ ctx->fb_dmabuffers[i] = imx_vpu_dma_buffer_allocate(imx_vpu_dec_get_default_allocator(), ctx->calculated_sizes.total_size, ctx->initial_info.framebuffer_alignment, 0); imx_vpu_fill_framebuffer_params(&(ctx->framebuffers[i]), &(ctx->calculated_sizes), ctx->fb_dmabuffers[i], 0); } /* allocate DMA buffers for the raw input frames. Since the encoder can only read * raw input pixels from a DMA memory region, it is necessary to allocate one, * and later copy the pixels into it. In production, it is generally a better * idea to make sure that the raw input frames are already placed in DMA memory * (either allocated by imx_vpu_dma_buffer_allocate() or by some other means of * getting DMA / physically contiguous memory with known physical addresses). */ ctx->input_fb_dmabuffer = imx_vpu_dma_buffer_allocate(imx_vpu_dec_get_default_allocator(), ctx->calculated_sizes.total_size, ctx->initial_info.framebuffer_alignment, 0); imx_vpu_fill_framebuffer_params(&(ctx->input_framebuffer), &(ctx->calculated_sizes), ctx->input_fb_dmabuffer, 0); /* Actual registration is done here. From this moment on, the VPU knows which buffers to use for * storing temporary frames into. This call must not be done again until encoding is shut down. */ imx_vpu_enc_register_framebuffers(ctx->vpuenc, ctx->framebuffers, ctx->num_framebuffers); return ctx; }
Context* init(FILE *input_file, FILE *output_file) { Context *ctx; ImxVpuEncOpenParams open_params; unsigned int i; ctx = calloc(1, sizeof(Context)); ctx->fin = input_file; ctx->fout = output_file; imx_vpu_enc_set_default_open_params(IMX_VPU_CODEC_FORMAT_H264, &open_params); open_params.frame_width = FRAME_WIDTH; open_params.frame_height = FRAME_HEIGHT; open_params.framerate = FPS; imx_vpu_enc_load(); imx_vpu_enc_get_bitstream_buffer_info(&(ctx->bitstream_buffer_size), &(ctx->bitstream_buffer_alignment)); ctx->bitstream_buffer = imx_vpu_dma_buffer_allocate(imx_vpu_enc_get_default_allocator(), ctx->bitstream_buffer_size, ctx->bitstream_buffer_alignment, 0); imx_vpu_enc_open(&(ctx->vpuenc), &open_params, ctx->bitstream_buffer); imx_vpu_enc_get_initial_info(ctx->vpuenc, &(ctx->initial_info)); ctx->num_framebuffers = ctx->initial_info.min_num_required_framebuffers; fprintf(stderr, "num framebuffers: %u\n", ctx->num_framebuffers); imx_vpu_calc_framebuffer_sizes(COLOR_FORMAT, FRAME_WIDTH, FRAME_HEIGHT, ctx->initial_info.framebuffer_alignment, 0, &(ctx->calculated_sizes)); fprintf( stderr, "calculated sizes: frame width&height: %dx%d Y stride: %u CbCr stride: %u Y size: %u CbCr size: %u MvCol size: %u total size: %u\n", ctx->calculated_sizes.aligned_frame_width, ctx->calculated_sizes.aligned_frame_height, ctx->calculated_sizes.y_stride, ctx->calculated_sizes.cbcr_stride, ctx->calculated_sizes.y_size, ctx->calculated_sizes.cbcr_size, ctx->calculated_sizes.mvcol_size, ctx->calculated_sizes.total_size ); ctx->framebuffers = malloc(sizeof(ImxVpuFramebuffer) * ctx->num_framebuffers); ctx->fb_dmabuffers = malloc(sizeof(ImxVpuDMABuffer*) * ctx->num_framebuffers); for (i = 0; i < ctx->num_framebuffers; ++i) { /* Allocate a DMA buffer for each framebuffer. It is possible to specify alternate allocators; * all that is required is that the allocator provides physically contiguous memory * (necessary for DMA transfers) and respecs the alignment value. */ ctx->fb_dmabuffers[i] = imx_vpu_dma_buffer_allocate(imx_vpu_dec_get_default_allocator(), ctx->calculated_sizes.total_size, ctx->initial_info.framebuffer_alignment, 0); imx_vpu_fill_framebuffer_params(&(ctx->framebuffers[i]), &(ctx->calculated_sizes), ctx->fb_dmabuffers[i], 0); } /* allocate DMA buffers for the input and output buffers. Use total_size as size for both; * the output buffer will most likely contain data later that is much smaller than the input, * but just to be on the safe side, make sure that even an uncompressed frame could fit */ ctx->input_fb_dmabuffer = imx_vpu_dma_buffer_allocate(imx_vpu_dec_get_default_allocator(), ctx->calculated_sizes.total_size, ctx->initial_info.framebuffer_alignment, 0); imx_vpu_fill_framebuffer_params(&(ctx->input_framebuffer), &(ctx->calculated_sizes), ctx->input_fb_dmabuffer, 0); ctx->output_dmabuffer = imx_vpu_dma_buffer_allocate(imx_vpu_dec_get_default_allocator(), ctx->calculated_sizes.total_size, ctx->initial_info.framebuffer_alignment, 0); /* Actual registration is done here. From this moment on, the VPU knows which buffers to use for * storing temporary pictures into. This call must not be done again until encoding is shut down. */ imx_vpu_enc_register_framebuffers(ctx->vpuenc, ctx->framebuffers, ctx->num_framebuffers); return ctx; }