* @remarks
* @see __mmcamcorder_create_preview_pipeline()
*/
+
static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
+static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview2(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
static int __mmcamcorder_get_amrnb_bitrate_mode(int bitrate);
}
+static gboolean __mmcamcorder_add_videofilter_element(mmf_camcorder_t *hcamcorder,
+ GList *element_list, const char *conf_prefix,
+ const char *filter_nick, _MMCAMCORDER_PREVIEW_PIPELINE_ELELMENT filter_index,
+ const char *queue_nick, _MMCAMCORDER_PREVIEW_PIPELINE_ELELMENT queue_index)
+{
+ int i = 0;
+ int err = MM_ERROR_NONE;
+ int videofilt_crop_rect[_MMCAMCORDER_CROP_ARRAY_LENGTH] = {0, };
+ char conf_name_element[CONFIGURE_FIELD_NAME_LENGTH] = {'\0',};
+ char conf_name_crop[_MMCAMCORDER_CROP_ARRAY_LENGTH][CONFIGURE_FIELD_NAME_LENGTH] = {{'\0',}, };
+ const char *conf_postfix_crop[_MMCAMCORDER_CROP_ARRAY_LENGTH] = {
+ "CropX",
+ "CropY",
+ "CropW",
+ "CropH"
+ };
+
+ _MMCamcorderSubContext *sc = NULL;
+ type_element *videofilt_element = NULL;
+ const char *videofilt_name = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+ mmf_return_val_if_fail(element_list, FALSE);
+ mmf_return_val_if_fail(filter_nick && filter_index > _MMCAMCORDER_NONE, FALSE);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+ mmf_return_val_if_fail(sc, FALSE);
+
+ snprintf(conf_name_element, sizeof(conf_name_element), "%sElement", conf_prefix);
+
+ _mmcamcorder_conf_get_element_and_name((MMHandleType)hcamcorder,
+ hcamcorder->conf_ctrl, CONFIGURE_CATEGORY_CTRL_CAMERA, conf_name_element,
+ &videofilt_element, &videofilt_name);
+
+ if (!videofilt_element || !videofilt_name) {
+ MMCAM_LOG_INFO("No configure for %s", conf_name_element);
+ return TRUE;
+ }
+
+ _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, filter_index, videofilt_name, filter_nick, element_list, err);
+ _mmcamcorder_conf_set_value_element_property(sc->element[filter_index].gst, videofilt_element);
+
+ for (i = 0 ; i < _MMCAMCORDER_CROP_ARRAY_LENGTH ; i++) {
+ snprintf(conf_name_crop[i], sizeof(conf_name_crop[i]), "%s%s", conf_prefix, conf_postfix_crop[i]);
+ _mmcamcorder_conf_get_value_int((MMHandleType)hcamcorder, hcamcorder->conf_ctrl,
+ CONFIGURE_CATEGORY_CTRL_CAMERA,
+ conf_name_crop[i], &videofilt_crop_rect[i]);
+ }
+
+ if (videofilt_crop_rect[0] >= 0 && videofilt_crop_rect[1] >= 0 &&
+ videofilt_crop_rect[2] > 0 && videofilt_crop_rect[3] > 0) {
+ _mmcamcorder_set_property_array_int(sc->element[filter_index].gst,
+ "crop", videofilt_crop_rect, _MMCAMCORDER_CROP_ARRAY_LENGTH);
+ }
+
+ MMCAM_LOG_INFO("queue_nick[%p], queue_index[%d]", queue_nick, queue_index);
+
+ if (queue_nick && queue_index > _MMCAMCORDER_NONE)
+ _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, queue_index, "queue", queue_nick, element_list, err);
+
+ return TRUE;
+
+pipeline_creation_error:
+ MMCAM_LOG_ERROR("failed[0x%x]", err);
+ return FALSE;
+}
+
+
int _mmcamcorder_create_preview_elements(MMHandleType handle)
{
int err = MM_ERROR_NONE;
int anti_shake = 0;
int display_surface_type = MM_DISPLAY_SURFACE_NULL;
const char *videosrc_name = NULL;
- const char *videofilt_name = NULL;
const char *videosink_name = NULL;
const char *videoconvert_name = NULL;
const char *videodecoder_name = NULL;
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
_MMCamcorderSubContext *sc = NULL;
type_element *videosrc_element = NULL;
- type_element *videofilt_element = NULL;
type_int_array *input_index = NULL;
mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
&hcamcorder->recreate_decoder);
}
- _mmcamcorder_conf_get_element_and_name((MMHandleType)hcamcorder,
- hcamcorder->conf_ctrl, CONFIGURE_CATEGORY_CTRL_CAMERA, "VideoFilterElement",
- &videofilt_element, &videofilt_name);
- if (videofilt_element && videofilt_name) {
- int videofilt_crop_rect[_MMCAMCORDER_CROP_ARRAY_LENGTH] = {0, };
- const char *conf_name[_MMCAMCORDER_CROP_ARRAY_LENGTH] = {
- "VideoFilterCropX",
- "VideoFilterCropY",
- "VideoFilterCropW",
- "VideoFilterCropH"
- };
-
- _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSRC_FILT, videofilt_name, "vsrc_f", element_list, err);
- _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, videofilt_element);
-
- for (i = 0 ; i < _MMCAMCORDER_CROP_ARRAY_LENGTH ; i++) {
- _mmcamcorder_conf_get_value_int((MMHandleType)hcamcorder, hcamcorder->conf_ctrl,
- CONFIGURE_CATEGORY_CTRL_CAMERA,
- conf_name[i], &videofilt_crop_rect[i]);
- }
-
- if (videofilt_crop_rect[0] >= 0 && videofilt_crop_rect[1] >= 0 &&
- videofilt_crop_rect[2] > 0 && videofilt_crop_rect[3] > 0) {
- _mmcamcorder_set_property_array_int(sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst,
- "crop", videofilt_crop_rect, _MMCAMCORDER_CROP_ARRAY_LENGTH);
- }
+ if (!__mmcamcorder_add_videofilter_element(hcamcorder, element_list, "VideoFilter",
+ "vsrc_f", _MMCAMCORDER_VIDEOSRC_FILT, NULL, _MMCAMCORDER_NONE)) {
+ MMCAM_LOG_ERROR("add videofilter failed for VideoFilterElement");
+ goto pipeline_creation_error;
}
_MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSRC_QUE, "queue", "vsrc_q", element_list, err);
+ if (!__mmcamcorder_add_videofilter_element(hcamcorder, element_list, "VideoFilter2",
+ "vsrc_f2", _MMCAMCORDER_VIDEOSRC_FILT2, "vsrc_q2", _MMCAMCORDER_VIDEOSRC_QUE2)) {
+ MMCAM_LOG_ERROR("add videofilter failed for VideoFilter2Element");
+ goto pipeline_creation_error;
+ }
+
if (display_surface_type != MM_DISPLAY_SURFACE_NULL &&
_mmcamcorder_is_encoded_preview_pixel_format(sc->info_image->preview_format)) {
switch (sc->info_image->preview_format) {
pipeline_creation_error:
_MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_SRC);
_MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_CAPS);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_FILT);
_MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_QUE);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_FILT2);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_QUE2);
_MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_CAP_CAPS);
_MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_CAP_SINK);
_MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_DECODE);
goto pipeline_creation_error;
/* Set data probe function */
- if (sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst) {
- MMCAM_LOG_INFO("add video dataprobe to videosrc queue");
- srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "src");
- } else {
+ if (!sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst) {
MMCAM_LOG_ERROR("there is no queue plugin");
goto pipeline_creation_error;
}
- if (srcpad) {
+ MMCAM_LOG_INFO("add video dataprobe to videosrc queue");
+ srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "src");
+ if (!srcpad) {
+ MMCAM_LOG_ERROR("failed to get srcpad");
+ goto pipeline_creation_error;
+ }
+
+ MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_PREVIEW,
+ __mmcamcorder_video_dataprobe_preview, hcamcorder);
+
+ gst_object_unref(srcpad);
+
+ if (sc->element[_MMCAMCORDER_VIDEOSRC_QUE2].gst) {
+ MMCAM_LOG_INFO("add video dataprobe2 to videosrc queue2");
+ srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_QUE2].gst, "src");
+ if (!srcpad) {
+ MMCAM_LOG_ERROR("failed to get srcpad");
+ goto pipeline_creation_error;
+ }
+
MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_PREVIEW,
- __mmcamcorder_video_dataprobe_preview, hcamcorder);
+ __mmcamcorder_video_dataprobe_preview2, hcamcorder);
gst_object_unref(srcpad);
- } else {
- MMCAM_LOG_ERROR("failed to get srcpad");
- goto pipeline_creation_error;
}
/* set dataprobe for video recording if it does not support dual stream. */
return GST_MAKE_FOURCC('N', 'O', 'N', 'E');
}
+
+static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview_common(mmf_camcorder_t *hcamcorder,
+ GstPad *pad, GstBuffer *buffer, int stream_id, int flag_mask)
+{
+ int flag_current = 0;
+ int ret_attr = MM_ERROR_NONE;
+ _MMCamcorderSubContext *sc = NULL;
+ g_autoptr(GstSample) sample = NULL;
+ g_autoptr(GstCaps) caps = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP);
+ mmf_return_val_if_fail(gst_buffer_n_memory(buffer), GST_PAD_PROBE_DROP);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+ mmf_return_val_if_fail(sc, GST_PAD_PROBE_DROP);
+
+ /* The first H.264 frame should not be skipped for vstream cb. */
+ if (hcamcorder->state < MM_CAMCORDER_STATE_PREPARE &&
+ !_mmcamcorder_is_encoded_preview_pixel_format(sc->info_image->preview_format)) {
+ MMCAM_LOG_WARNING("Not ready for stream callback[stream_id:%d]", stream_id);
+ return GST_PAD_PROBE_OK;
+ }
+
+ ret_attr = mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
+ MMCAM_VIDEO_STREAM_CALLBACK_FLAG, &flag_current,
+ NULL);
+ if (ret_attr != MM_ERROR_NONE) {
+ MMCAM_LOG_WARNING("get preview callback flag failed[0x%x]", ret_attr);
+ return GST_PAD_PROBE_OK;
+ }
+
+ MMCAM_LOG_DEBUG("flag [current:0x%08x,mask:0x%08x]", flag_current, flag_mask);
+
+ if (!(flag_current & flag_mask))
+ return GST_PAD_PROBE_OK;
+
+ /* make sample with buffer and caps */
+ caps = gst_pad_get_current_caps(pad);
+ mmf_return_val_if_fail(caps, GST_PAD_PROBE_OK);
+
+ sample = gst_sample_new(buffer, caps, NULL, NULL);
+ mmf_return_val_if_fail(sample, GST_PAD_PROBE_OK);
+
+ return _mmcamcorder_invoke_video_stream_cb((MMHandleType)hcamcorder, sample, TRUE, stream_id) ? \
+ GST_PAD_PROBE_OK : GST_PAD_PROBE_DROP;
+}
+
+
static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
{
- gboolean ret = TRUE;
mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
_MMCamcorderSubContext *sc = NULL;
GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
- GstSample *sample = NULL;
- GstCaps *caps = NULL;
- mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP);
- mmf_return_val_if_fail(gst_buffer_n_memory(buffer), GST_PAD_PROBE_DROP);
mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP);
+ mmf_return_val_if_fail(gst_buffer_n_memory(buffer), GST_PAD_PROBE_DROP);
sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
mmf_return_val_if_fail(sc, GST_PAD_PROBE_DROP);
if (hcamcorder->measure_preview_fps && hcamcorder->state >= MM_CAMCORDER_STATE_PREPARE)
_mmcamcorder_measure_fps(&sc->kpi);
- /* The first H.264 frame should not be skipped for vstream cb. */
- if (hcamcorder->state < MM_CAMCORDER_STATE_PREPARE &&
- !_mmcamcorder_is_encoded_preview_pixel_format(sc->info_image->preview_format)) {
- MMCAM_LOG_WARNING("Not ready for stream callback");
- return GST_PAD_PROBE_OK;
- }
-
- /* make sample with buffer and caps */
- caps = gst_pad_get_current_caps(pad);
- mmf_return_val_if_fail(caps, GST_PAD_PROBE_OK);
-
- sample = gst_sample_new(buffer, caps, NULL, NULL);
- gst_caps_unref(caps);
- mmf_return_val_if_fail(sample, GST_PAD_PROBE_OK);
-
- ret = _mmcamcorder_invoke_video_stream_cb((MMHandleType)hcamcorder, sample, TRUE, -1);
+ return __mmcamcorder_video_dataprobe_preview_common(hcamcorder,
+ pad, buffer,
+ MM_CAMCORDER_VIDEO_STREAM_ID_NORMAL,
+ MM_CAMCORDER_VIDEO_STREAM_CALLBACK_FLAG_NORMAL);
+}
- gst_sample_unref(sample);
- if (ret)
- return GST_PAD_PROBE_OK;
- else
- return GST_PAD_PROBE_DROP;
+static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview2(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
+{
+ return __mmcamcorder_video_dataprobe_preview_common(MMF_CAMCORDER(u_data),
+ pad, GST_PAD_PROBE_INFO_BUFFER(info),
+ MM_CAMCORDER_VIDEO_STREAM_ID_INTERNAL,
+ MM_CAMCORDER_VIDEO_STREAM_CALLBACK_FLAG_INTERNAL);
}
return TRUE;
}
+
+int _mmcamcorder_set_video_stream_callback_flag(MMHandleType handle, gboolean enable, int flag)
+{
+ int ret = MM_ERROR_NONE;
+ int flag_current = MM_CAMCORDER_VIDEO_STREAM_CALLBACK_FLAG_NONE;
+ int flag_new = MM_CAMCORDER_VIDEO_STREAM_CALLBACK_FLAG_NONE;
+
+ MMCAM_LOG_INFO("enable[%d], flag[0x%08x]", enable, flag);
+
+ _MMCAMCORDER_LOCK_VSTREAM_CALLBACK_FLAG(handle);
+
+ ret = mm_camcorder_get_attributes(handle, NULL,
+ MMCAM_VIDEO_STREAM_CALLBACK_FLAG, &flag_current,
+ NULL);
+ if (ret != MM_ERROR_NONE) {
+ MMCAM_LOG_ERROR("get vstream callback flag failed[0x%x]", ret);
+ goto _SET_VIDEO_STREAM_CALLBACK_FLAG_DONE;
+ }
+
+ MMCAM_LOG_INFO("current flag[0x%08x]", flag_current);
+
+ if (enable)
+ flag_new = flag_current | flag;
+ else
+ flag_new = flag_current & ~flag;
+
+ ret = mm_camcorder_set_attributes(handle, NULL,
+ MMCAM_VIDEO_STREAM_CALLBACK_FLAG, flag_new,
+ NULL);
+ if (ret != MM_ERROR_NONE) {
+ MMCAM_LOG_ERROR("set vstream callback flag[0x%x] failed[0x%x]", flag_new, ret);
+ goto _SET_VIDEO_STREAM_CALLBACK_FLAG_DONE;
+ }
+
+ MMCAM_LOG_INFO("new flag[0x%08x]", flag_new);
+
+_SET_VIDEO_STREAM_CALLBACK_FLAG_DONE:
+ _MMCAMCORDER_UNLOCK_VSTREAM_CALLBACK_FLAG(handle);
+
+ return ret;
+}
+
+
#ifdef _MMCAMCORDER_PRODUCT_TV
bool __mmcamcorder_find_max_resolution(MMHandleType handle, gint *max_width, gint *max_height)
{