ImxVpuDecReturnCodes imx_vpu_dec_close(ImxVpuDecoder *decoder) { VpuDecRetCode ret; IMX_VPU_TRACE("closing decoder"); ret = VPU_DecFlushAll(decoder->handle); if (ret == VPU_DEC_RET_FAILURE_TIMEOUT) { IMX_VPU_WARNING("resetting decoder after a timeout occurred"); ret = VPU_DecReset(decoder->handle); if (ret != VPU_DEC_RET_SUCCESS) IMX_VPU_ERROR("resetting decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret))); } else if (ret != VPU_DEC_RET_SUCCESS) IMX_VPU_ERROR("flushing decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret))); ret = VPU_DecClose(decoder->handle); if (ret != VPU_DEC_RET_SUCCESS) IMX_VPU_ERROR("closing decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret))); if (decoder->user_data_for_frames != NULL) IMX_VPU_FREE(decoder->user_data_for_frames, sizeof(void*) * decoder->num_framebuffers); if (decoder->wrapper_framebuffers != NULL) IMX_VPU_FREE(decoder->wrapper_framebuffers, sizeof(VpuFrameBuffer*) * decoder->num_framebuffers); if (decoder->virt_mem_sub_block != NULL) IMX_VPU_FREE(decoder->virt_mem_sub_block, decoder->virt_mem_sub_block_size); IMX_VPU_FREE(decoder, sizeof(ImxVpuDecoder)); IMX_VPU_TRACE("closed decoder"); return dec_convert_retcode(ret); }
ImxVpuDecReturnCodes imx_vpu_dec_flush(ImxVpuDecoder *decoder) { VpuDecRetCode ret = VPU_DEC_RET_SUCCESS; decoder->delay_pending_user_data = FALSE; if (decoder->flush_vpu_upon_reset) { ret = VPU_DecFlushAll(decoder->handle); if (ret == VPU_DEC_RET_FAILURE_TIMEOUT) { IMX_VPU_WARNING("resetting decoder after a timeout occurred"); ret = VPU_DecReset(decoder->handle); if (ret != VPU_DEC_RET_SUCCESS) IMX_VPU_ERROR("resetting decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret))); } else if (ret != VPU_DEC_RET_SUCCESS) IMX_VPU_ERROR("flushing decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret))); else IMX_VPU_INFO("flushed decoder"); decoder->recalculate_num_avail_framebuffers = TRUE; } else IMX_VPU_INFO("decoder not flushed, because it is unnecessary for this codec format"); if (decoder->user_data_for_frames != NULL) memset(decoder->user_data_for_frames, 0, sizeof(void*) * decoder->num_framebuffers); decoder->num_user_data = 0; return dec_convert_retcode(ret); }
ImxVpuDecReturnCodes imx_vpu_dec_mark_framebuffer_as_displayed(ImxVpuDecoder *decoder, ImxVpuFramebuffer const *framebuffer) { VpuDecRetCode ret; VpuFrameBuffer *wrapper_fb = (VpuFrameBuffer *)(framebuffer->internal); ret = VPU_DecOutFrameDisplayed(decoder->handle, wrapper_fb); if (ret != VPU_DEC_RET_SUCCESS) { ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret); IMX_VPU_ERROR("error marking output frame as displayed: %s", imx_vpu_dec_error_string(imxret)); return imxret; } IMX_VPU_LOG("marked framebuffer %p with physical address 0x%x as displayed", (void *)framebuffer, framebuffer->physical_address); if (decoder->num_times_counter_decremented > 0) { decoder->num_available_framebuffers++; decoder->num_times_counter_decremented--; decoder->num_framebuffers_in_use--; IMX_VPU_LOG("num_available_framebuffers %d num_times_counter_decremented %d num_framebuffers_in_use %d", decoder->num_available_framebuffers, decoder->num_times_counter_decremented, decoder->num_framebuffers_in_use); } return IMX_VPU_DEC_RETURN_CODE_OK; }
ImxVpuDecReturnCodes imx_vpu_dec_get_decoded_frame(ImxVpuDecoder *decoder, ImxVpuDecodedFrame *decoded_frame) { VpuDecRetCode ret; VpuDecOutFrameInfo out_frame_info; int fb_index; void *user_data; ret = VPU_DecGetOutputFrame(decoder->handle, &out_frame_info); if (ret != VPU_DEC_RET_SUCCESS) { ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret); IMX_VPU_ERROR("error getting decoded output frame: %s", imx_vpu_dec_error_string(imxret)); return imxret; } fb_index = dec_get_wrapper_framebuffer_index(decoder, out_frame_info.pDisplayFrameBuf); user_data = NULL; if (decoder->consumption_info_available) { if ((fb_index >= 0) && (fb_index < (int)(decoder->num_framebuffers))) { user_data = decoder->user_data_for_frames[fb_index]; IMX_VPU_LOG("framebuffer index %d for framebuffer %p and user data %p", fb_index, (void *)(out_frame_info.pDisplayFrameBuf), user_data); decoder->user_data_for_frames[fb_index] = NULL; } else IMX_VPU_ERROR("framebuffer index %d for framebuffer %p and user data %p out of bounds", fb_index, (void *)(out_frame_info.pDisplayFrameBuf), user_data); } else { if (decoder->num_user_data > 0) { user_data = decoder->user_data_for_frames[0]; decoder->user_data_for_frames[0] = NULL; IMX_VPU_LOG("framebuffer index %d user data %p retrieved as oldest", fb_index, user_data); memmove(decoder->user_data_for_frames, decoder->user_data_for_frames + 1, sizeof(void*) * (decoder->num_user_data - 1)); decoder->num_user_data--; } } decoded_frame->pic_type = convert_from_wrapper_pic_type(out_frame_info.ePicType); decoded_frame->user_data = user_data; /* XXX * This association assumes that the order of internal framebuffer entries * inside the VPU wrapper is the same as the order of the framebuffers here. * So, decoder->framebuffers[1] equals internal framebuffer entry with index 1 etc. */ decoded_frame->framebuffer = &(decoder->framebuffers[fb_index]); /* This is used in imx_vpu_dec_mark_framebuffer_as_displayed() to be able * to mark the vpuwrapper framebuffer as displayed */ decoded_frame->framebuffer->internal = out_frame_info.pDisplayFrameBuf; decoder->num_framebuffers_in_use++; return IMX_VPU_DEC_RETURN_CODE_OK; }
ImxVpuDecReturnCodes imx_vpu_dec_register_framebuffers(ImxVpuDecoder *decoder, ImxVpuFramebuffer *framebuffers, unsigned int num_framebuffers) { unsigned int i; VpuDecRetCode ret; VpuFrameBuffer *temp_fbs; IMX_VPU_TRACE("attempting to register %u framebuffers", num_framebuffers); decoder->wrapper_framebuffers = NULL; temp_fbs = IMX_VPU_ALLOC(sizeof(VpuFrameBuffer) * num_framebuffers); if (temp_fbs == NULL) { IMX_VPU_ERROR("allocating memory for framebuffers failed"); return IMX_VPU_DEC_RETURN_CODE_ERROR; } for (i = 0; i < num_framebuffers; ++i) convert_to_wrapper_framebuffer(&framebuffers[i], &(temp_fbs[i])); ret = VPU_DecRegisterFrameBuffer(decoder->handle, temp_fbs, num_framebuffers); IMX_VPU_FREE(temp_fbs, sizeof(VpuFrameBuffer) * num_framebuffers); if (ret != VPU_DEC_RET_SUCCESS) { ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret); IMX_VPU_ERROR("registering framebuffers failed: %s", imx_vpu_dec_error_string(imxret)); return ret; } decoder->wrapper_framebuffers = IMX_VPU_ALLOC(sizeof(VpuFrameBuffer*) * num_framebuffers); { int out_num; VPU_DecAllRegFrameInfo(decoder->handle, decoder->wrapper_framebuffers, &out_num); IMX_VPU_LOG("out_num: %d num_framebuffers: %u", out_num, num_framebuffers); } decoder->framebuffers = framebuffers; decoder->num_framebuffers = num_framebuffers; decoder->num_available_framebuffers = num_framebuffers; decoder->user_data_for_frames = IMX_VPU_ALLOC(sizeof(void*) * num_framebuffers); if (decoder->user_data_for_frames == NULL) { IMX_VPU_ERROR("allocating memory for user data failed"); IMX_VPU_FREE(decoder->wrapper_framebuffers, sizeof(VpuFrameBuffer*) * num_framebuffers); decoder->wrapper_framebuffers = NULL; return IMX_VPU_DEC_RETURN_CODE_ERROR; } memset(decoder->user_data_for_frames, 0, sizeof(void*) * num_framebuffers); decoder->num_user_data = 0; return IMX_VPU_DEC_RETURN_CODE_OK; }
ImxVpuDecReturnCodes imx_vpu_dec_set_drain_mode(ImxVpuDecoder *decoder, int enabled) { int config_param; VpuDecRetCode ret; config_param = enabled ? VPU_DEC_IN_DRAIN : VPU_DEC_IN_NORMAL; ret = VPU_DecConfig(decoder->handle, VPU_DEC_CONF_INPUTTYPE, &config_param); if (ret != VPU_DEC_RET_SUCCESS) IMX_VPU_ERROR("setting decoder drain mode failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret))); else IMX_VPU_INFO("set decoder drain mode to %d", enabled); return dec_convert_retcode(ret); }
ImxVpuDecReturnCodes imx_vpu_dec_unload(void) { IMX_VPU_TRACE("VPU load instance counter: %lu", vpu_load_inst_counter); if (vpu_load_inst_counter == 0) return IMX_VPU_DEC_RETURN_CODE_OK; ImxVpuDecReturnCodes ret = dec_convert_retcode(VPU_DecUnLoad()); if (ret != IMX_VPU_DEC_RETURN_CODE_OK) IMX_VPU_ERROR("unloading decoder failed: %s", imx_vpu_dec_error_string(ret)); else { IMX_VPU_TRACE("unloaded decoder"); --vpu_load_inst_counter; } return ret; }
ImxVpuDecReturnCodes imx_vpu_dec_decode_frame(ImxVpuDecoder *decoder, ImxVpuEncodedFrame const *encoded_frame, unsigned int *output_code) { VpuDecRetCode ret; VpuBufferNode node; int buf_ret_code; node.pVirAddr = encoded_frame->virtual_address; node.pPhyAddr = 0; /* encoded data is always read from a regular memory block, not a DMA buffer */ node.nSize = encoded_frame->data_size; node.sCodecData.pData = encoded_frame->codec_data; node.sCodecData.nSize = encoded_frame->codec_data_size; decoder->pending_user_data = encoded_frame->user_data; ret = VPU_DecDecodeBuf(decoder->handle, &node, &buf_ret_code); IMX_VPU_LOG("VPU_DecDecodeBuf buf ret code: 0x%x", buf_ret_code); *output_code = dec_convert_outcode(buf_ret_code); if (ret != VPU_DEC_RET_SUCCESS) { IMX_VPU_ERROR("decoding frame failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret))); return dec_convert_retcode(ret); } if (decoder->recalculate_num_avail_framebuffers) { decoder->num_available_framebuffers = decoder->num_framebuffers - decoder->num_framebuffers_in_use; IMX_VPU_LOG("recalculated number of available framebuffers to %d", decoder->num_available_framebuffers); decoder->recalculate_num_avail_framebuffers = FALSE; } if (buf_ret_code & VPU_DEC_INIT_OK) { decoder->delay_pending_user_data = TRUE; decoder->last_pending_user_data = decoder->pending_user_data; } if (buf_ret_code & VPU_DEC_FLUSH) { IMX_VPU_INFO("VPU requested a decoder flush"); ret = VPU_DecFlushAll(decoder->handle); if (ret == VPU_DEC_RET_FAILURE_TIMEOUT) { IMX_VPU_WARNING("timeout detected, resetting decoder"); ret = VPU_DecReset(decoder->handle); if (ret != VPU_DEC_RET_SUCCESS) { ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret); IMX_VPU_ERROR("resetting decoder failed: %s", imx_vpu_dec_error_string(imxret)); return imxret; } else *output_code |= IMX_VPU_DEC_OUTPUT_CODE_INTERNAL_RESET; } else if (ret != VPU_DEC_RET_SUCCESS) { ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret); IMX_VPU_ERROR("flushing decoder failed: %s", imx_vpu_dec_error_string(imxret)); return imxret; } else IMX_VPU_INFO("flushed decoder"); } if (buf_ret_code & VPU_DEC_RESOLUTION_CHANGED) { IMX_VPU_INFO("resolution changed - resetting internal states"); *output_code |= IMX_VPU_DEC_OUTPUT_CODE_INITIAL_INFO_AVAILABLE; decoder->delay_pending_user_data = TRUE; decoder->recalculate_num_avail_framebuffers = FALSE; decoder->num_user_data = 0; if (decoder->user_data_for_frames != NULL) IMX_VPU_FREE(decoder->user_data_for_frames, sizeof(void*) * decoder->num_framebuffers); if (decoder->wrapper_framebuffers != NULL) IMX_VPU_FREE(decoder->wrapper_framebuffers, sizeof(VpuFrameBuffer*) * decoder->num_framebuffers); decoder->user_data_for_frames = NULL; decoder->wrapper_framebuffers = NULL; } if (buf_ret_code & VPU_DEC_NO_ENOUGH_INBUF) { /* Not dropping frame here on purpose; the next input frame may * complete the input */ } { void *user_data = decoder->delay_pending_user_data ? decoder->last_pending_user_data : decoder->pending_user_data; /* The first time this location is reached, VPU_DEC_INIT_OK will be set in the output_code. * This implies that the framebuffers have not been allocated and registered yet, * so no user data can be stored yet. * With codec formats that produce consumption info, this is not a problem, because * VPU_DEC_ONE_FRM_CONSUMED will be returned only when framebuffers are present. * But with other formats, an explicit decoder->framebuffers != NULL check is necessary * (see below). The user_data pointer does not get lost; it is stored in last_pending_user_data. */ if ((buf_ret_code & VPU_DEC_ONE_FRM_CONSUMED) && !(buf_ret_code & VPU_DEC_OUTPUT_DROPPED)) { int fb_index; VpuDecFrameLengthInfo consumed_frame_info; ret = VPU_DecGetConsumedFrameInfo(decoder->handle, &consumed_frame_info); if (ret != VPU_DEC_RET_SUCCESS) { ImxVpuDecReturnCodes imxret = dec_convert_retcode(ret); IMX_VPU_ERROR("getting consumed frame info failed: %s", imx_vpu_dec_error_string(imxret)); return imxret; } fb_index = dec_get_wrapper_framebuffer_index(decoder, consumed_frame_info.pFrame); if (consumed_frame_info.pFrame != NULL) { if ((fb_index >= 0) && (fb_index < (int)(decoder->num_framebuffers))) { IMX_VPU_LOG("framebuffer index %d for framebuffer %p user data %p", fb_index, (void *)(consumed_frame_info.pFrame), user_data); decoder->user_data_for_frames[fb_index] = user_data; } else IMX_VPU_ERROR("framebuffer index %d for framebuffer %p user data %p out of bounds", fb_index, (void *)(consumed_frame_info.pFrame), user_data); } else IMX_VPU_WARNING("consumed frame info contains a NULL frame"); } else if (!(decoder->consumption_info_available) && (decoder->framebuffers != NULL)) { if (decoder->num_user_data < (int)(decoder->num_framebuffers)) { decoder->user_data_for_frames[decoder->num_user_data] = user_data; decoder->num_user_data++; IMX_VPU_LOG("user data %p stored as newest", user_data); IMX_VPU_TRACE("incremented number of userdata pointers to %d", decoder->num_user_data); } else IMX_VPU_WARNING("too many user data pointers in memory - cannot store current one"); } decoder->last_pending_user_data = decoder->pending_user_data; decoder->pending_user_data = NULL; } if ((buf_ret_code & VPU_DEC_ONE_FRM_CONSUMED) && !(buf_ret_code & VPU_DEC_OUTPUT_DROPPED)) { decoder->num_available_framebuffers--; decoder->num_times_counter_decremented++; IMX_VPU_LOG("decremented number of available framebuffers to %d (with consumed frame info); number of times decremented is now %d", decoder->num_available_framebuffers, decoder->num_times_counter_decremented); } if (buf_ret_code & VPU_DEC_OUTPUT_NODIS) { if ((encoded_frame->virtual_address != NULL) && (decoder->codec_format == IMX_VPU_CODEC_FORMAT_VP8)) *output_code |= IMX_VPU_DEC_OUTPUT_CODE_DECODE_ONLY; } /* VPU_DEC_NO_ENOUGH_BUF handled by caller - should be treated as an error */ if ((buf_ret_code & VPU_DEC_OUTPUT_DIS) && !(decoder->consumption_info_available)) { decoder->num_available_framebuffers--; decoder->num_times_counter_decremented++; IMX_VPU_LOG("decremented number of available framebuffers to %d (no consumed frame info); number of times decremented is now %d", decoder->num_available_framebuffers, decoder->num_times_counter_decremented); } else if (buf_ret_code & VPU_DEC_OUTPUT_MOSAIC_DIS) { IMX_VPU_TRACE("dropping mosaic frame"); /* mosaic frames do not seem to be useful for anything, so they are just dropped here */ ImxVpuDecReturnCodes imxret; ImxVpuDecodedFrame decoded_frame; if ((imxret = imx_vpu_dec_get_decoded_frame(decoder, &decoded_frame)) != IMX_VPU_DEC_RETURN_CODE_OK) { IMX_VPU_ERROR("error getting output mosaic frame: %s", imx_vpu_dec_error_string(imxret)); return imxret; } if ((imxret = imx_vpu_dec_mark_framebuffer_as_displayed(decoder, decoded_frame.framebuffer)) != IMX_VPU_DEC_RETURN_CODE_OK) { IMX_VPU_ERROR("error marking mosaic frame as displayed: %s", imx_vpu_dec_error_string(imxret)); return imxret; } decoder->dropped_frame_user_data = decoded_frame.user_data; *output_code |= IMX_VPU_DEC_OUTPUT_CODE_DROPPED; } else if (buf_ret_code & VPU_DEC_OUTPUT_DROPPED) { // TODO make this work for formats with consumption info if (decoder->num_user_data > 0) { decoder->dropped_frame_user_data = decoder->user_data_for_frames[0]; decoder->user_data_for_frames[0] = NULL; memmove(decoder->user_data_for_frames, decoder->user_data_for_frames + 1, sizeof(void*) * (decoder->num_user_data - 1)); decoder->num_user_data--; } else decoder->dropped_frame_user_data = NULL; } /* In case the VPU didn't use the input and no consumed frame info is available, * drop the input frame to make sure timestamps are okay * (If consumed frame info is present it is still possible it might be used for input-output frame * associations; unlikely to occur thought) */ if ((encoded_frame->virtual_address != NULL) && !(buf_ret_code & (VPU_DEC_ONE_FRM_CONSUMED | VPU_DEC_INPUT_USED | VPU_DEC_RESOLUTION_CHANGED))) { decoder->dropped_frame_user_data = encoded_frame->user_data; *output_code |= IMX_VPU_DEC_OUTPUT_CODE_DROPPED; } return IMX_VPU_DEC_RETURN_CODE_OK; }
ImxVpuDecReturnCodes imx_vpu_dec_open(ImxVpuDecoder **decoder, ImxVpuDecOpenParams const *open_params, void *bitstream_buffer_virtual_address, imx_vpu_phys_addr_t bitstream_buffer_physical_addres) { int config_param; VpuDecRetCode ret; VpuMemInfo mem_info; VpuDecOpenParam open_param; *decoder = IMX_VPU_ALLOC(sizeof(ImxVpuDecoder)); if ((*decoder) == NULL) { IMX_VPU_ERROR("allocating memory for decoder object failed"); return IMX_VPU_DEC_RETURN_CODE_ERROR; } memset(*decoder, 0, sizeof(ImxVpuDecoder)); { int i; VPU_DecQueryMem(&mem_info); IMX_VPU_INFO("about to allocate %d memory sub blocks", mem_info.nSubBlockNum); for (i = 0; i < mem_info.nSubBlockNum; ++i) { char const *type_str = "<unknown>"; VpuMemSubBlockInfo *sub_block = &(mem_info.MemSubBlock[i]); switch (sub_block->MemType) { case VPU_MEM_VIRT: type_str = "virtual"; (*decoder)->virt_mem_sub_block_size = sub_block->nSize + sub_block->nAlignment; (*decoder)->virt_mem_sub_block = IMX_VPU_ALLOC((*decoder)->virt_mem_sub_block_size); if ((*decoder)->virt_mem_sub_block == NULL) { IMX_VPU_ERROR("allocating memory for sub block failed"); return IMX_VPU_DEC_RETURN_CODE_ERROR; } sub_block->pVirtAddr = (unsigned char *)IMX_VPU_ALIGN_VAL_TO((*decoder)->virt_mem_sub_block, sub_block->nAlignment); sub_block->pPhyAddr = 0; break; case VPU_MEM_PHY: type_str = "physical"; sub_block->pVirtAddr = (unsigned char *)(bitstream_buffer_virtual_address); sub_block->pPhyAddr = (unsigned char *)(bitstream_buffer_physical_addres); break; default: break; } IMX_VPU_INFO("allocated memory sub block #%d: type: %s size: %d alignment: %d virtual address: %p physical address: %p", i, type_str, sub_block->nSize, sub_block->nAlignment, sub_block->pVirtAddr, sub_block->pPhyAddr); } } dec_convert_to_wrapper_open_param(open_params, &open_param); IMX_VPU_TRACE("opening decoder"); switch (open_params->codec_format) { case IMX_VPU_CODEC_FORMAT_H264: case IMX_VPU_CODEC_FORMAT_H264_MVC: case IMX_VPU_CODEC_FORMAT_MPEG2: case IMX_VPU_CODEC_FORMAT_MPEG4: (*decoder)->consumption_info_available = TRUE; (*decoder)->flush_vpu_upon_reset = TRUE; break; case IMX_VPU_CODEC_FORMAT_H263: case IMX_VPU_CODEC_FORMAT_WMV3: case IMX_VPU_CODEC_FORMAT_WVC1: (*decoder)->consumption_info_available = FALSE; (*decoder)->flush_vpu_upon_reset = FALSE; break; case IMX_VPU_CODEC_FORMAT_MJPEG: case IMX_VPU_CODEC_FORMAT_VP8: (*decoder)->consumption_info_available = FALSE; (*decoder)->flush_vpu_upon_reset = TRUE; break; default: break; } ret = VPU_DecOpen(&((*decoder)->handle), &open_param, &mem_info); if (ret != VPU_DEC_RET_SUCCESS) { IMX_VPU_ERROR("opening decoder failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret))); goto cleanup; } IMX_VPU_TRACE("setting configuration"); config_param = VPU_DEC_SKIPNONE; ret = VPU_DecConfig((*decoder)->handle, VPU_DEC_CONF_SKIPMODE, &config_param); if (ret != VPU_DEC_RET_SUCCESS) { IMX_VPU_ERROR("setting skipmode to NONE failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret))); goto cleanup; } config_param = 0; ret = VPU_DecConfig((*decoder)->handle, VPU_DEC_CONF_BUFDELAY, &config_param); if (ret != VPU_DEC_RET_SUCCESS) { IMX_VPU_ERROR("setting bufdelay to 0 failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret))); goto cleanup; } config_param = VPU_DEC_IN_NORMAL; ret = VPU_DecConfig((*decoder)->handle, VPU_DEC_CONF_INPUTTYPE, &config_param); if (ret != VPU_DEC_RET_SUCCESS) { IMX_VPU_ERROR("setting input type to \"normal\" failed: %s", imx_vpu_dec_error_string(dec_convert_retcode(ret))); goto cleanup; } (*decoder)->codec_format = open_params->codec_format; finish: if (ret == VPU_DEC_RET_SUCCESS) IMX_VPU_TRACE("successfully opened decoder"); return dec_convert_retcode(ret); cleanup: if ((*decoder)->virt_mem_sub_block != NULL) IMX_VPU_FREE((*decoder)->virt_mem_sub_block, (*decoder)->virt_mem_sub_block_size); IMX_VPU_FREE(*decoder, sizeof(ImxVpuDecoder)); *decoder = NULL; goto finish; }
ImxVpuDecReturnCodes imx_vpu_dec_deallocate_memory(ImxVpuMemBlock *mem_block) { ImxVpuDecReturnCodes ret; VpuMemDesc mem_desc; convert_to_wrapper_mem_desc(mem_block, &mem_desc); ret = dec_convert_retcode(VPU_DecFreeMem(&mem_desc)); if (ret != IMX_VPU_DEC_RETURN_CODE_OK) IMX_VPU_ERROR("deallocating %d bytes of physical memory failed: %s", mem_block->size, imx_vpu_dec_error_string(ret)); else IMX_VPU_TRACE("deallocated %d bytes of physical memory", mem_block->size); return ret; }
ImxVpuDecReturnCodes imx_vpu_dec_allocate_memory(ImxVpuMemBlock *mem_block) { VpuDecRetCode ret; VpuMemDesc mem_desc; if (mem_block->alignment == 0) mem_block->alignment = 1; mem_desc.nSize = mem_block->size + mem_block->alignment; if ((ret = VPU_DecGetMem(&mem_desc)) != VPU_DEC_RET_SUCCESS) { IMX_VPU_ERROR("allocating %d bytes of physical memory failed: %s", mem_block->size, imx_vpu_dec_error_string(dec_convert_retcode(ret))); return dec_convert_retcode(ret); } else IMX_VPU_TRACE("allocated %d bytes of physical memory", mem_block->size); convert_from_wrapper_mem_desc(&mem_desc, mem_block); mem_block->virtual_address = (void *)IMX_VPU_ALIGN_VAL_TO(mem_block->virtual_address_unaligned, mem_block->alignment); mem_block->physical_address = (imx_vpu_phys_addr_t)IMX_VPU_ALIGN_VAL_TO(mem_block->physical_address_unaligned, mem_block->alignment); return IMX_VPU_DEC_RETURN_CODE_OK; }
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; }