static ImxVpuEncReturnCodes imx_vpu_jpeg_enc_open_internal(ImxVpuJPEGEncoder *jpeg_encoder) { unsigned int i; ImxVpuEncOpenParams open_params; ImxVpuEncReturnCodes ret = IMX_VPU_ENC_RETURN_CODE_OK; assert(jpeg_encoder != NULL); assert(jpeg_encoder->frame_width > 0); assert(jpeg_encoder->frame_height > 0); assert(jpeg_encoder->encoder == NULL); imx_vpu_enc_set_default_open_params(IMX_VPU_CODEC_FORMAT_MJPEG, &open_params); open_params.frame_width = jpeg_encoder->frame_width; open_params.frame_height = jpeg_encoder->frame_height; open_params.codec_params.mjpeg_params.quality_factor = jpeg_encoder->quality_factor; if ((ret = imx_vpu_enc_open(&(jpeg_encoder->encoder), &open_params, jpeg_encoder->bitstream_buffer)) != IMX_VPU_ENC_RETURN_CODE_OK) goto error; if ((ret = imx_vpu_enc_get_initial_info(jpeg_encoder->encoder, &(jpeg_encoder->initial_info))) != IMX_VPU_ENC_RETURN_CODE_OK) goto error; jpeg_encoder->num_framebuffers = jpeg_encoder->initial_info.min_num_required_framebuffers; jpeg_encoder->framebuffers = IMX_VPU_ALLOC(sizeof(ImxVpuFramebuffer) * jpeg_encoder->num_framebuffers); jpeg_encoder->fb_dmabuffers = IMX_VPU_ALLOC(sizeof(ImxVpuDMABuffer *) * jpeg_encoder->num_framebuffers); memset(jpeg_encoder->framebuffers, 0, sizeof(ImxVpuFramebuffer) * jpeg_encoder->num_framebuffers); memset(jpeg_encoder->fb_dmabuffers, 0, sizeof(ImxVpuDMABuffer *) * jpeg_encoder->num_framebuffers); imx_vpu_calc_framebuffer_sizes(jpeg_encoder->color_format, jpeg_encoder->frame_width, jpeg_encoder->frame_height, jpeg_encoder->initial_info.framebuffer_alignment, 0, 0, &(jpeg_encoder->calculated_sizes)); for (i = 0; i < jpeg_encoder->num_framebuffers; ++i) { jpeg_encoder->fb_dmabuffers[i] = imx_vpu_dma_buffer_allocate(jpeg_encoder->dma_buffer_allocator, jpeg_encoder->calculated_sizes.total_size, jpeg_encoder->initial_info.framebuffer_alignment, 0); if (jpeg_encoder->fb_dmabuffers[i] == NULL) { IMX_VPU_ERROR("could not allocate DMA buffer for framebuffer #%u", i); ret = IMX_VPU_ENC_RETURN_CODE_ERROR; goto error; } imx_vpu_fill_framebuffer_params(&(jpeg_encoder->framebuffers[i]), &(jpeg_encoder->calculated_sizes), jpeg_encoder->fb_dmabuffers[i], 0); } if ((ret = imx_vpu_enc_register_framebuffers(jpeg_encoder->encoder, jpeg_encoder->framebuffers, jpeg_encoder->num_framebuffers)) != IMX_VPU_ENC_RETURN_CODE_OK) { IMX_VPU_ERROR("could not register framebuffers: %s", imx_vpu_enc_error_string(ret)); goto error; } return ret; error: imx_vpu_jpeg_enc_close_internal(jpeg_encoder); return ret; }
ImxVpuDecReturnCodes imx_vpu_jpeg_dec_open(ImxVpuJPEGDecoder **jpeg_decoder, ImxVpuDMABufferAllocator *dma_buffer_allocator, unsigned int num_extra_framebuffers) { ImxVpuDecOpenParams open_params; ImxVpuDecReturnCodes ret = IMX_VPU_DEC_RETURN_CODE_OK; ImxVpuJPEGDecoder *jpegdec = NULL; assert(jpeg_decoder != NULL); if ((ret = imx_vpu_dec_load()) != IMX_VPU_DEC_RETURN_CODE_OK) return ret; jpegdec = IMX_VPU_ALLOC(sizeof(ImxVpuJPEGDecoder)); if (jpegdec == NULL) { IMX_VPU_ERROR("allocating memory for JPEG decoder object failed"); return IMX_VPU_DEC_RETURN_CODE_ERROR; } memset(jpegdec, 0, sizeof(ImxVpuJPEGDecoder)); jpegdec->dma_buffer_allocator = (dma_buffer_allocator != NULL) ? dma_buffer_allocator : imx_vpu_dec_get_default_allocator(); jpegdec->num_extra_framebuffers = num_extra_framebuffers; memset(&open_params, 0, sizeof(open_params)); open_params.codec_format = IMX_VPU_CODEC_FORMAT_MJPEG; open_params.frame_width = 0; open_params.frame_height = 0; imx_vpu_dec_get_bitstream_buffer_info(&(jpegdec->bitstream_buffer_size), &(jpegdec->bitstream_buffer_alignment)); jpegdec->bitstream_buffer = imx_vpu_dma_buffer_allocate(jpegdec->dma_buffer_allocator, jpegdec->bitstream_buffer_size, jpegdec->bitstream_buffer_alignment, 0); if (jpegdec->bitstream_buffer == NULL) { IMX_VPU_ERROR("could not allocate DMA buffer for bitstream buffer with %u bytes and alignment %u", jpegdec->bitstream_buffer_size, jpegdec->bitstream_buffer_alignment); ret = IMX_VPU_DEC_RETURN_CODE_ERROR; goto error; } if ((ret = imx_vpu_dec_open(&(jpegdec->decoder), &open_params, jpegdec->bitstream_buffer, initial_info_callback, jpegdec)) != IMX_VPU_DEC_RETURN_CODE_OK) goto error; *jpeg_decoder = jpegdec; return IMX_VPU_DEC_RETURN_CODE_OK; error: if (jpegdec != NULL) { if (jpegdec->bitstream_buffer != NULL) imx_vpu_dma_buffer_deallocate(jpegdec->bitstream_buffer); IMX_VPU_FREE(jpegdec, sizeof(ImxVpuJPEGDecoder)); } 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; ImxVpuDecOpenParams open_params; ctx = calloc(1, sizeof(Context)); ctx->fin = input_file; ctx->fout = output_file; open_params.codec_format = IMX_VPU_CODEC_FORMAT_MJPEG; open_params.frame_width = 0; open_params.frame_height = 0; imx_vpu_dec_load(); imx_vpu_dec_get_bitstream_buffer_info(&(ctx->bitstream_buffer_size), &(ctx->bitstream_buffer_alignment)); ctx->bitstream_buffer = imx_vpu_dma_buffer_allocate(imx_vpu_dec_get_default_allocator(), ctx->bitstream_buffer_size, ctx->bitstream_buffer_alignment, 0); imx_vpu_dec_open(&(ctx->vpudec), &open_params, ctx->bitstream_buffer); 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; /* 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; }
Retval run(Context *ctx) { unsigned int output_code; { long size; void *buf; fseek(ctx->fin, 0, SEEK_END); size = ftell(ctx->fin); fseek(ctx->fin, 0, SEEK_SET); buf = malloc(size); fread(buf, 1, size, ctx->fin); ImxVpuEncodedFrame encoded_frame; encoded_frame.data.virtual_address = buf; encoded_frame.data_size = size; /* Codec data is out-of-band data that is typically stored in a separate space * in containers for each elementary stream; JPEG data does not need it */ encoded_frame.codec_data = NULL; encoded_frame.codec_data_size = 0; fprintf(stderr, "encoded input frame: size: %u byte\n", encoded_frame.data_size); /* Perform the actual decoding */ imx_vpu_dec_decode(ctx->vpudec, &encoded_frame, &output_code); free(buf); } /* Initial info is now available; this usually happens right after the * first frame is decoded, and this is the situation where one must register * output framebuffers, which the decoder then uses like a buffer pool for * picking buffers to decode frame into */ if (output_code & IMX_VPU_DEC_OUTPUT_CODE_INITIAL_INFO_AVAILABLE) { unsigned int i; imx_vpu_dec_get_initial_info(ctx->vpudec, &(ctx->initial_info)); fprintf( stderr, "initial info: size: %ux%u pixel rate: %u/%u min num required framebuffers: %u interlacing: %d framebuffer alignment: %u color format: ", ctx->initial_info.frame_width, ctx->initial_info.frame_height, ctx->initial_info.frame_rate_numerator, ctx->initial_info.frame_rate_denominator, ctx->initial_info.min_num_required_framebuffers, ctx->initial_info.interlacing, ctx->initial_info.framebuffer_alignment ); switch (ctx->initial_info.color_format) { case IMX_VPU_COLOR_FORMAT_YUV420: fprintf(stderr, "YUV 4:2:0"); break; case IMX_VPU_COLOR_FORMAT_YUV422_HORIZONTAL: fprintf(stderr, "YUV 4:2:2 horizontal"); break; case IMX_VPU_COLOR_FORMAT_YUV422_VERTICAL: fprintf(stderr, "YUV 4:2:2 vertical"); break; case IMX_VPU_COLOR_FORMAT_YUV444: fprintf(stderr, "YUV 4:4:4"); break; case IMX_VPU_COLOR_FORMAT_YUV400: fprintf(stderr, "YUV 4:0:0 (8-bit grayscale)"); break; } fprintf(stderr, "\n"); ctx->num_framebuffers = ctx->initial_info.min_num_required_framebuffers; imx_vpu_calc_framebuffer_sizes(ctx->initial_info.color_format, ctx->initial_info.frame_width, ctx->initial_info.frame_height, ctx->initial_info.framebuffer_alignment, ctx->initial_info.interlacing, &(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); } /* Actual registration is done here. From this moment on, the VPU knows which buffers to use for * storing decoded pictures into. This call must not be done again until decoding is shut down or * IMX_VPU_DEC_OUTPUT_CODE_INITIAL_INFO_AVAILABLE is set again. */ imx_vpu_dec_register_framebuffers(ctx->vpudec, ctx->framebuffers, ctx->num_framebuffers); } /* Enable drain mode. All available input data is * inserted. Now We want one output picture. */ imx_vpu_dec_enable_drain_mode(ctx->vpudec, 1); /* Get the decoded picture out of the VPU */ { ImxVpuEncodedFrame encoded_frame; /* In drain mode there is no input data */ encoded_frame.data.virtual_address = NULL; encoded_frame.data_size = 0; encoded_frame.codec_data = NULL; encoded_frame.codec_data_size = 0; encoded_frame.context = NULL; imx_vpu_dec_decode(ctx->vpudec, &encoded_frame, &output_code); /* A decoded picture is available for further processing. Retrieve it, do something * with it, and once the picture is no longer needed, mark it as displayed. This * marks it internally as available for further decoding by the VPU. */ if (output_code & IMX_VPU_DEC_OUTPUT_CODE_DECODED_PICTURE_AVAILABLE) { ImxVpuPicture decoded_picture; uint8_t *mapped_virtual_address; size_t num_out_byte = ctx->calculated_sizes.y_size + ctx->calculated_sizes.cbcr_size * 2; /* This call retrieves information about the decoded picture, including * a pointer to the corresponding framebuffer structure. This must not be called more * than once after IMX_VPU_DEC_OUTPUT_CODE_DECODED_PICTURE_AVAILABLE was set. */ imx_vpu_dec_get_decoded_picture(ctx->vpudec, &decoded_picture); fprintf(stderr, "decoded output picture: writing %u byte", num_out_byte); /* Map buffer to the local address space, dump the decoded frame to file, * and unmap again. The decoded frame uses the I420 color format for all * bitstream formats (h.264, MPEG2 etc.), with one exception; with motion JPEG data, * the format can be different. See imxvpuapi.h for details. */ mapped_virtual_address = imx_vpu_dma_buffer_map(decoded_picture.framebuffer->dma_buffer, IMX_VPU_MAPPING_FLAG_READ_ONLY); fwrite(mapped_virtual_address, 1, num_out_byte, ctx->fout); imx_vpu_dma_buffer_unmap(decoded_picture.framebuffer->dma_buffer); /* Mark the framebuffer as displayed, thus returning it to the list of *framebuffers available for decoding. */ imx_vpu_dec_mark_framebuffer_as_displayed(ctx->vpudec, decoded_picture.framebuffer); } } return RETVAL_OK; }
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; }
static int initial_info_callback(ImxVpuDecoder *decoder, ImxVpuDecInitialInfo *new_initial_info, unsigned int output_code, void *user_data) { unsigned int i; ImxVpuDecReturnCodes ret; ImxVpuJPEGDecoder *jpeg_decoder = (ImxVpuJPEGDecoder *)user_data; IMXVPUAPI_UNUSED_PARAM(decoder); IMXVPUAPI_UNUSED_PARAM(output_code); imx_vpu_jpeg_dec_deallocate_framebuffers(jpeg_decoder); jpeg_decoder->initial_info = *new_initial_info; IMX_VPU_DEBUG( "initial info: size: %ux%u pixel rate: %u/%u min num required framebuffers: %u interlacing: %d framebuffer alignment: %u color format: %s", new_initial_info->frame_width, new_initial_info->frame_height, new_initial_info->frame_rate_numerator, new_initial_info->frame_rate_denominator, new_initial_info->min_num_required_framebuffers, new_initial_info->interlacing, new_initial_info->framebuffer_alignment, imx_vpu_color_format_string(new_initial_info->color_format) ); jpeg_decoder->num_framebuffers = new_initial_info->min_num_required_framebuffers + jpeg_decoder->num_extra_framebuffers; imx_vpu_calc_framebuffer_sizes(new_initial_info->color_format, new_initial_info->frame_width, new_initial_info->frame_height, new_initial_info->framebuffer_alignment, new_initial_info->interlacing, 0, &(jpeg_decoder->calculated_sizes)); IMX_VPU_DEBUG( "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", jpeg_decoder->calculated_sizes.aligned_frame_width, jpeg_decoder->calculated_sizes.aligned_frame_height, jpeg_decoder->calculated_sizes.y_stride, jpeg_decoder->calculated_sizes.cbcr_stride, jpeg_decoder->calculated_sizes.y_size, jpeg_decoder->calculated_sizes.cbcr_size, jpeg_decoder->calculated_sizes.mvcol_size, jpeg_decoder->calculated_sizes.total_size ); jpeg_decoder->framebuffers = IMX_VPU_ALLOC(sizeof(ImxVpuFramebuffer) * jpeg_decoder->num_framebuffers); jpeg_decoder->fb_dmabuffers = IMX_VPU_ALLOC(sizeof(ImxVpuDMABuffer *) * jpeg_decoder->num_framebuffers); memset(jpeg_decoder->framebuffers, 0, sizeof(ImxVpuFramebuffer) * jpeg_decoder->num_framebuffers); memset(jpeg_decoder->fb_dmabuffers, 0, sizeof(ImxVpuDMABuffer *) * jpeg_decoder->num_framebuffers); for (i = 0; i < jpeg_decoder->num_framebuffers; ++i) { jpeg_decoder->fb_dmabuffers[i] = imx_vpu_dma_buffer_allocate(jpeg_decoder->dma_buffer_allocator, jpeg_decoder->calculated_sizes.total_size, jpeg_decoder->initial_info.framebuffer_alignment, 0); if (jpeg_decoder->fb_dmabuffers[i] == NULL) { IMX_VPU_ERROR("could not allocate DMA buffer for framebuffer #%u", i); goto error; } imx_vpu_fill_framebuffer_params(&(jpeg_decoder->framebuffers[i]), &(jpeg_decoder->calculated_sizes), jpeg_decoder->fb_dmabuffers[i], 0); } if ((ret = imx_vpu_dec_register_framebuffers(jpeg_decoder->decoder, jpeg_decoder->framebuffers, jpeg_decoder->num_framebuffers)) != IMX_VPU_DEC_RETURN_CODE_OK) { IMX_VPU_ERROR("could not register framebuffers: %s", imx_vpu_dec_error_string(ret)); goto error; } return 1; error: imx_vpu_jpeg_deallocate_dma_buffers(jpeg_decoder->fb_dmabuffers, jpeg_decoder->num_framebuffers); return 0; }