static GstMemory * _fallback_mem_copy (GstMemory * mem, gssize offset, gssize size) { GstMemory *copy; GstMapInfo sinfo, dinfo; GstAllocationParams params = { 0, mem->align, 0, 0, }; GstAllocator *allocator; if (!gst_memory_map (mem, &sinfo, GST_MAP_READ)) return NULL; if (size == -1) size = sinfo.size > offset ? sinfo.size - offset : 0; /* use the same allocator as the memory we copy */ allocator = mem->allocator; if (GST_OBJECT_FLAG_IS_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC)) allocator = NULL; copy = gst_allocator_alloc (allocator, size, ¶ms); if (!gst_memory_map (copy, &dinfo, GST_MAP_WRITE)) { GST_CAT_WARNING (GST_CAT_MEMORY, "could not write map memory %p", copy); gst_allocator_free (mem->allocator, copy); gst_memory_unmap (mem, &sinfo); return NULL; } GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "memcpy %" G_GSSIZE_FORMAT " memory %p -> %p", size, mem, copy); memcpy (dinfo.data, sinfo.data + offset, size); gst_memory_unmap (copy, &dinfo); gst_memory_unmap (mem, &sinfo); return copy; }
static gboolean gst_imx_vpu_base_enc_stop(GstVideoEncoder *encoder) { gboolean ret; GstImxVpuBaseEnc *vpu_base_enc; ret = TRUE; vpu_base_enc = GST_IMX_VPU_BASE_ENC(encoder); if (vpu_base_enc->framebuffers != NULL) { gst_object_unref(vpu_base_enc->framebuffers); vpu_base_enc->framebuffers = NULL; } if (vpu_base_enc->output_phys_buffer != NULL) { gst_allocator_free(gst_imx_vpu_enc_allocator_obtain(), (GstMemory *)(vpu_base_enc->output_phys_buffer)); vpu_base_enc->output_phys_buffer = NULL; } gst_imx_vpu_base_enc_close_encoder(vpu_base_enc); gst_imx_vpu_base_enc_free_enc_mem_blocks(vpu_base_enc); gst_imx_vpu_base_enc_unload(); return ret; }
static void gst_imx_vpu_base_enc_close_encoder(GstImxVpuBaseEnc *vpu_base_enc) { VpuEncRetCode enc_ret; if (vpu_base_enc->internal_input_buffer != NULL) { gst_buffer_unref(vpu_base_enc->internal_input_buffer); vpu_base_enc->internal_input_buffer = NULL; } if (vpu_base_enc->internal_bufferpool != NULL) { gst_object_unref(vpu_base_enc->internal_bufferpool); vpu_base_enc->internal_bufferpool = NULL; } if (vpu_base_enc->output_phys_buffer != NULL) { gst_allocator_free(gst_imx_vpu_enc_allocator_obtain(), (GstMemory *)(vpu_base_enc->output_phys_buffer)); vpu_base_enc->output_phys_buffer = NULL; } if (vpu_base_enc->vpu_inst_opened) { enc_ret = VPU_EncClose(vpu_base_enc->handle); if (enc_ret != VPU_ENC_RET_SUCCESS) GST_ERROR_OBJECT(vpu_base_enc, "closing encoder failed: %s", gst_imx_vpu_strerror(enc_ret)); vpu_base_enc->vpu_inst_opened = FALSE; } }
static void _gst_memory_free (GstMemory * mem) { GST_CAT_DEBUG (GST_CAT_MEMORY, "free memory %p", mem); if (mem->parent) { gst_memory_unlock (mem->parent, GST_LOCK_FLAG_EXCLUSIVE); gst_memory_unref (mem->parent); } gst_allocator_free (mem->allocator, mem); }
static gboolean gst_fsl_vpu_base_enc_stop(GstVideoEncoder *encoder) { gboolean ret; VpuEncRetCode enc_ret; GstFslVpuBaseEnc *vpu_base_enc; GstFslVpuBaseEncClass *klass; ret = TRUE; vpu_base_enc = GST_FSL_VPU_BASE_ENC(encoder); klass = GST_FSL_VPU_BASE_ENC_CLASS(G_OBJECT_GET_CLASS(vpu_base_enc)); if (vpu_base_enc->framebuffers != NULL) { gst_object_unref(vpu_base_enc->framebuffers); vpu_base_enc->framebuffers = NULL; } if (vpu_base_enc->output_phys_buffer != NULL) { gst_allocator_free(gst_fsl_vpu_enc_allocator_obtain(), (GstMemory *)(vpu_base_enc->output_phys_buffer)); vpu_base_enc->output_phys_buffer = NULL; } gst_fsl_vpu_base_enc_close_encoder(vpu_base_enc); gst_fsl_vpu_base_enc_free_enc_mem_blocks(vpu_base_enc); g_mutex_lock(&inst_counter_mutex); if (klass->inst_counter > 0) { --klass->inst_counter; if (klass->inst_counter == 0) { enc_ret = VPU_EncUnLoad(); if (enc_ret != VPU_ENC_RET_SUCCESS) { GST_ERROR_OBJECT(vpu_base_enc, "unloading VPU encoder failed: %s", gst_fsl_vpu_strerror(enc_ret)); } else GST_INFO_OBJECT(vpu_base_enc, "VPU encoder unloaded"); } } g_mutex_unlock(&inst_counter_mutex); return ret; }
gboolean gst_imx_vpu_free_phys_mem_blocks(GstImxPhysMemAllocator *phys_mem_allocator, GSList **phys_mem_blocks) { GSList *mem_block_node; setup_debug_category(); g_assert(phys_mem_blocks != NULL); mem_block_node = *phys_mem_blocks; if (mem_block_node == NULL) return TRUE; for (; mem_block_node != NULL; mem_block_node = mem_block_node->next) { GstMemory *memory = (GstMemory *)(mem_block_node->data); gst_allocator_free((GstAllocator *)phys_mem_allocator, memory); GST_INFO("freed phys memory block with %u bytes at phys addr 0x%x", memory->size, ((GstImxPhysMemory *)memory)->phys_addr); } g_slist_free(*phys_mem_blocks); *phys_mem_blocks = NULL; return TRUE; }
static gboolean gst_fsl_vpu_base_enc_set_format(GstVideoEncoder *encoder, GstVideoCodecState *state) { VpuEncRetCode ret; GstVideoCodecState *output_state; GstFslVpuBaseEncClass *klass; GstFslVpuBaseEnc *vpu_base_enc; vpu_base_enc = GST_FSL_VPU_BASE_ENC(encoder); klass = GST_FSL_VPU_BASE_ENC_CLASS(G_OBJECT_GET_CLASS(vpu_base_enc)); g_assert(klass->set_open_params != NULL); g_assert(klass->get_output_caps != NULL); /* Close old encoder instance */ gst_fsl_vpu_base_enc_close_encoder(vpu_base_enc); /* Clean up existing framebuffers structure; * if some previous and still existing buffer pools depend on this framebuffers * structure, they will extend its lifetime, since they ref'd it */ if (vpu_base_enc->framebuffers != NULL) { gst_object_unref(vpu_base_enc->framebuffers); vpu_base_enc->framebuffers = NULL; } if (vpu_base_enc->output_phys_buffer != NULL) { gst_allocator_free(gst_fsl_vpu_enc_allocator_obtain(), (GstMemory *)(vpu_base_enc->output_phys_buffer)); vpu_base_enc->output_phys_buffer = NULL; } memset(&(vpu_base_enc->open_param), 0, sizeof(VpuEncOpenParam)); /* These params are usually not set by derived classes */ vpu_base_enc->open_param.nPicWidth = GST_VIDEO_INFO_WIDTH(&(state->info)); vpu_base_enc->open_param.nPicHeight = GST_VIDEO_INFO_HEIGHT(&(state->info)); vpu_base_enc->open_param.nFrameRate = (GST_VIDEO_INFO_FPS_N(&(state->info)) & 0xffffUL) | (((GST_VIDEO_INFO_FPS_D(&(state->info)) - 1) & 0xffffUL) << 16); vpu_base_enc->open_param.sMirror = VPU_ENC_MIRDIR_NONE; /* don't use VPU rotation (IPU has better performance) */ vpu_base_enc->open_param.nBitRate = vpu_base_enc->bitrate; vpu_base_enc->open_param.nGOPSize = vpu_base_enc->gop_size; vpu_base_enc->open_param.nUserGamma = (int)(32768 * vpu_base_enc->qp_smoothing); vpu_base_enc->open_param.nAvcIntra16x16OnlyModeEnable = vpu_base_enc->intra_16x16_only ? 1 : 0; vpu_base_enc->open_param.nRcIntervalMode = 1; /* These params are defaults, and are often overwritten by derived classes */ vpu_base_enc->open_param.nUserQpMax = -1; vpu_base_enc->open_param.nUserQpMin = -1; vpu_base_enc->open_param.nRcIntraQp = -1; GST_DEBUG_OBJECT(vpu_base_enc, "setting bitrate to %u kbps and GOP size to %u", vpu_base_enc->open_param.nBitRate, vpu_base_enc->open_param.nGOPSize); /* Give the derived class a chance to set params */ if (!klass->set_open_params(vpu_base_enc, &(vpu_base_enc->open_param))) { GST_ERROR_OBJECT(vpu_base_enc, "derived class could not set open params"); return FALSE; } /* The actual initialization; requires bitstream information (such as the codec type), which * is determined by the fill_param_set call before */ ret = VPU_EncOpen(&(vpu_base_enc->handle), &(vpu_base_enc->mem_info), &(vpu_base_enc->open_param)); if (ret != VPU_ENC_RET_SUCCESS) { GST_ERROR_OBJECT(vpu_base_enc, "opening new VPU handle failed: %s", gst_fsl_vpu_strerror(ret)); return FALSE; } vpu_base_enc->vpu_inst_opened = TRUE; /* configure AFTER setting vpu_inst_opened to TRUE, to make sure that in case of config failure the VPU handle is closed in the finalizer */ ret = VPU_EncConfig(vpu_base_enc->handle, VPU_ENC_CONF_NONE, NULL); if (ret != VPU_ENC_RET_SUCCESS) { GST_ERROR_OBJECT(vpu_base_enc, "could not apply default configuration: %s", gst_fsl_vpu_strerror(ret)); return FALSE; } ret = VPU_EncGetInitialInfo(vpu_base_enc->handle, &(vpu_base_enc->init_info)); if (ret != VPU_ENC_RET_SUCCESS) { GST_ERROR_OBJECT(vpu_base_enc, "retrieving init info failed: %s", gst_fsl_vpu_strerror(ret)); return FALSE; } /* Framebuffers are created in handle_frame(), to make sure the actual stride is used */ /* Set the output state, using caps defined by the derived class */ output_state = gst_video_encoder_set_output_state( encoder, klass->get_output_caps(vpu_base_enc), state ); gst_video_codec_state_unref(output_state); vpu_base_enc->video_info = state->info; return TRUE; }
static gboolean gst_imx_vpu_base_enc_set_format(GstVideoEncoder *encoder, GstVideoCodecState *state) { VpuEncRetCode ret; GstVideoCodecState *output_state; GstImxVpuBaseEncClass *klass; GstImxVpuBaseEnc *vpu_base_enc; int param; vpu_base_enc = GST_IMX_VPU_BASE_ENC(encoder); klass = GST_IMX_VPU_BASE_ENC_CLASS(G_OBJECT_GET_CLASS(vpu_base_enc)); g_assert(klass->set_open_params != NULL); g_assert(klass->get_output_caps != NULL); /* Close old encoder instance */ gst_imx_vpu_base_enc_close_encoder(vpu_base_enc); /* Clean up existing framebuffers structure; * if some previous and still existing buffer pools depend on this framebuffers * structure, they will extend its lifetime, since they ref'd it */ if (vpu_base_enc->framebuffers != NULL) { gst_object_unref(vpu_base_enc->framebuffers); vpu_base_enc->framebuffers = NULL; } if (vpu_base_enc->output_phys_buffer != NULL) { gst_allocator_free(gst_imx_vpu_enc_allocator_obtain(), (GstMemory *)(vpu_base_enc->output_phys_buffer)); vpu_base_enc->output_phys_buffer = NULL; } memset(&(vpu_base_enc->open_param), 0, sizeof(VpuEncOpenParam)); /* These params are usually not set by derived classes */ vpu_base_enc->open_param.nPicWidth = GST_VIDEO_INFO_WIDTH(&(state->info)); vpu_base_enc->open_param.nPicHeight = GST_VIDEO_INFO_HEIGHT(&(state->info)); vpu_base_enc->open_param.nFrameRate = (GST_VIDEO_INFO_FPS_N(&(state->info)) & 0xffffUL) | (((GST_VIDEO_INFO_FPS_D(&(state->info)) - 1) & 0xffffUL) << 16); vpu_base_enc->open_param.sMirror = VPU_ENC_MIRDIR_NONE; /* don't use VPU mirroring (IPU has better performance) */ vpu_base_enc->open_param.nBitRate = vpu_base_enc->bitrate; vpu_base_enc->open_param.nGOPSize = vpu_base_enc->gop_size; GST_INFO_OBJECT(vpu_base_enc, "setting bitrate to %u kbps and GOP size to %u", vpu_base_enc->open_param.nBitRate, vpu_base_enc->open_param.nGOPSize); /* These are default settings from VPU_EncOpenSimp */ vpu_base_enc->open_param.sliceMode.sliceMode = 0; /* 1 slice per picture */ vpu_base_enc->open_param.sliceMode.sliceSizeMode = 0; /* sliceSize is bits */ vpu_base_enc->open_param.sliceMode.sliceSize = 4000; vpu_base_enc->open_param.nRcIntraQp = -1; vpu_base_enc->open_param.nUserGamma = 0.75 * 32768; if (vpu_base_enc->slice_size) { vpu_base_enc->open_param.sliceMode.sliceMode = 1; /* 0: 1 slice per picture; 1: Multiple slices per picture */ if (vpu_base_enc->slice_size < 0) { vpu_base_enc->open_param.sliceMode.sliceSizeMode = 1; /* 1: sliceSize defined by MB number*/ vpu_base_enc->open_param.sliceMode.sliceSize = -vpu_base_enc->slice_size; /* Size of a slice in MB numbers */ } else { vpu_base_enc->open_param.sliceMode.sliceSizeMode = 0; /* 1: sliceSize defined by bits */ vpu_base_enc->open_param.sliceMode.sliceSize = vpu_base_enc->slice_size; /* Size of a slice in bits */ } } vpu_base_enc->open_param.nIntraRefresh = vpu_base_enc->intra_refresh; /* Give the derived class a chance to set params */ if (!klass->set_open_params(vpu_base_enc, state, &(vpu_base_enc->open_param))) { GST_ERROR_OBJECT(vpu_base_enc, "derived class could not set open params"); return FALSE; } /* The actual initialization; requires bitstream information (such as the codec type), which * is determined by the fill_param_set call before */ ret = VPU_EncOpen(&(vpu_base_enc->handle), &(vpu_base_enc->mem_info), &(vpu_base_enc->open_param)); if (ret != VPU_ENC_RET_SUCCESS) { GST_ERROR_OBJECT(vpu_base_enc, "opening new VPU handle failed: %s", gst_imx_vpu_strerror(ret)); return FALSE; } vpu_base_enc->vpu_inst_opened = TRUE; /* configure AFTER setting vpu_inst_opened to TRUE, to make sure that in case of config failure the VPU handle is closed in the finalizer */ if (vpu_base_enc->bitrate != 0) { param = vpu_base_enc->bitrate; ret = VPU_EncConfig(vpu_base_enc->handle, VPU_ENC_CONF_BIT_RATE, ¶m); if (ret != VPU_ENC_RET_SUCCESS) { GST_ERROR_OBJECT(vpu_base_enc, "could not configure bitrate: %s", gst_imx_vpu_strerror(ret)); return FALSE; } } if (vpu_base_enc->intra_refresh != 0) { param = vpu_base_enc->intra_refresh; ret = VPU_EncConfig(vpu_base_enc->handle, VPU_ENC_CONF_INTRA_REFRESH, ¶m); if (ret != VPU_ENC_RET_SUCCESS) { GST_ERROR_OBJECT(vpu_base_enc, "could not configure intra refresh period: %s", gst_imx_vpu_strerror(ret)); return FALSE; } } ret = VPU_EncGetInitialInfo(vpu_base_enc->handle, &(vpu_base_enc->init_info)); if (ret != VPU_ENC_RET_SUCCESS) { GST_ERROR_OBJECT(vpu_base_enc, "retrieving init info failed: %s", gst_imx_vpu_strerror(ret)); return FALSE; } /* Framebuffers are created in handle_frame(), to make sure the actual stride is used */ /* Set the output state, using caps defined by the derived class */ output_state = gst_video_encoder_set_output_state( encoder, klass->get_output_caps(vpu_base_enc), state ); gst_video_codec_state_unref(output_state); vpu_base_enc->video_info = state->info; return TRUE; }