+
+
+bool _mmcamcorder_set_encoded_preview_bitrate(MMHandleType handle, int bitrate)
+{
+ _MMCamcorderSubContext *sc = NULL;
+
+ if ((void *)handle == NULL) {
+ _mmcam_dbg_warn("handle is NULL");
+ return FALSE;
+ }
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc) {
+ _mmcam_dbg_warn("subcontext is NULL");
+ return FALSE;
+ }
+
+ if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst == NULL) {
+ _mmcam_dbg_warn("videosrc plugin is NULL");
+ return FALSE;
+ }
+
+ _mmcam_dbg_log("set encoded preview bitrate : %d bps", bitrate);
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "bitrate", bitrate);
+
+ return TRUE;
+}
+
+
+bool _mmcamcorder_set_encoded_preview_gop_interval(MMHandleType handle, int gop_interval)
+{
+ _MMCamcorderSubContext *sc = NULL;
+
+ if ((void *)handle == NULL) {
+ _mmcam_dbg_warn("handle is NULL");
+ return FALSE;
+ }
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc) {
+ _mmcam_dbg_warn("subcontext is NULL");
+ return FALSE;
+ }
+
+ if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst == NULL) {
+ _mmcam_dbg_warn("videosrc plugin is NULL");
+ return FALSE;
+ }
+
+ _mmcam_dbg_log("set encoded preview GOP interval : %d ms", gop_interval);
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "gop-interval", gop_interval);
+
+ return TRUE;
+}
+
+
+bool _mmcamcorder_set_sound_stream_info(GstElement *element, char *stream_type, int stream_index)
+{
+ GstStructure *props = NULL;
+ char stream_props[64] = {'\0',};
+
+ if (element == NULL || stream_type == NULL || stream_index < 0) {
+ _mmcam_dbg_err("invalid argument %p %p %d", element, stream_type, stream_index);
+ return FALSE;
+ }
+
+ snprintf(stream_props, sizeof(stream_props) - 1,
+ "props,media.role=%s, media.parent_id=%d",
+ stream_type, stream_index);
+
+ _mmcam_dbg_warn("stream type %s, index %d -> [%s]", stream_type, stream_index, stream_props);
+
+ props = gst_structure_from_string(stream_props, NULL);
+ if (!props) {
+ _mmcam_dbg_err("failed to create GstStructure");
+ return FALSE;
+ }
+
+ MMCAMCORDER_G_OBJECT_SET_POINTER(element, "stream-properties", props);
+
+ gst_structure_free(props);
+ props = NULL;
+
+ return TRUE;
+}
+
+
+bool _mmcamcorder_recreate_decoder_for_encoded_preview(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ _MMCamcorderSubContext *sc = NULL;
+ mmf_camcorder_t *hcamcorder = NULL;
+ const char *videodecoder_name = NULL;
+#ifdef _MMCAMCORDER_RM_SUPPORT
+ char decoder_name[20] = {'\0',};
+ int decoder_index = 0;
+#endif /* _MMCAMCORDER_RM_SUPPORT */
+
+ if ((void *)handle == NULL) {
+ _mmcam_dbg_warn("handle is NULL");
+ return FALSE;
+ }
+
+ hcamcorder = MMF_CAMCORDER(handle);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc) {
+ _mmcam_dbg_warn("subcontext is NULL");
+ return FALSE;
+ }
+
+ if (sc->info_image->preview_format != MM_PIXEL_FORMAT_ENCODED_H264 ||
+ hcamcorder->recreate_decoder == FALSE) {
+ _mmcam_dbg_log("skip this fuction - format %d, recreate decoder %d",
+ sc->info_image->preview_format, hcamcorder->recreate_decoder);
+ return TRUE;
+ }
+
+ if (sc->element[_MMCAMCORDER_MAIN_PIPE].gst == NULL ||
+ sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst == NULL) {
+ _mmcam_dbg_warn("main pipeline or decoder plugin is NULL");
+ return FALSE;
+ }
+
+ _mmcam_dbg_log("start");
+
+ _mmcamcorder_conf_get_value_element_name(sc->VideodecoderElementH264, &videodecoder_name);
+ if (videodecoder_name == NULL) {
+ _mmcam_dbg_err("failed to get decoder element name from %p", sc->VideodecoderElementH264);
+ return FALSE;
+ }
+
+ /* set state as NULL */
+ ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst, GST_STATE_NULL);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("failed to set NULL to decoder");
+ return FALSE;
+ }
+
+ /* remove decoder - pads will be unlinked automatically in remove function */
+ if (!gst_bin_remove(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
+ sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst)) {
+ _mmcam_dbg_err("failed to remove decoder from pipeline");
+ return FALSE;
+ }
+
+ /* check decoder element */
+ if (sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst) {
+ _mmcam_dbg_log("decoder[%p] is still alive - ref count %d",
+ G_OBJECT(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst),
+ ((GObject *)sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst)->ref_count);
+ }
+
+#ifdef _MMCAMCORDER_RM_SUPPORT
+ if (hcamcorder->request_resources.category_id[0] == RM_CATEGORY_VIDEO_DECODER_SUB)
+ decoder_index = 1;
+
+ snprintf(decoder_name, sizeof(decoder_name)-1, "%s%d", videodecoder_name, decoder_index);
+ _mmcam_dbg_log("encoded preview decoder_name %s", decoder_name);
+ /* create decoder */
+ sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst = gst_element_factory_make(decoder_name, "videosrc_decode");
+ if (sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst == NULL) {
+ _mmcam_dbg_err("Decoder[%s] creation fail", decoder_name);
+ return FALSE;
+ }
+#else /* _MMCAMCORDER_RM_SUPPORT */
+ /* create new decoder */
+ sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst = gst_element_factory_make(videodecoder_name, "videosrc_decode");
+ if (sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst == NULL) {
+ _mmcam_dbg_err("Decoder [%s] creation fail", videodecoder_name);
+ return FALSE;
+ }
+#endif /* _MMCAMCORDER_RM_SUPPORT */
+ _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst, sc->VideodecoderElementH264);
+
+ sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].id = _MMCAMCORDER_VIDEOSRC_DECODE;
+ g_object_weak_ref(G_OBJECT(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst),
+ (GWeakNotify)_mmcamcorder_element_release_noti, sc);
+
+ /* add to pipeline */
+ if (!gst_bin_add(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
+ sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst)) {
+ _mmcam_dbg_err("failed to add decoder to pipeline");
+ gst_object_unref(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst);
+ return FALSE;
+ }
+
+ /* link */
+ if (_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst),
+ GST_ELEMENT(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst))) {
+ _mmcam_dbg_log("Link videosrc_queue to decoder OK");
+ } else {
+ _mmcam_dbg_err("Link videosrc_queue to decoder FAILED");
+ return FALSE;
+ }
+
+ if (_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst),
+ GST_ELEMENT(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst))) {
+ _mmcam_dbg_log("Link decoder to videosink_queue OK");
+ } else {
+ _mmcam_dbg_err("Link decoder to videosink_queue FAILED");
+ return FALSE;
+ }
+
+ /* set state READY */
+ ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst, GST_STATE_READY);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("failed to set READY to decoder");
+ return FALSE;
+ }
+
+ _mmcam_dbg_log("done");
+
+ return TRUE;
+}
+
+#ifdef _MMCAMCORDER_PRODUCT_TV
+static bool __mmcamcorder_find_max_resolution(MMHandleType handle, gint *max_width, gint *max_height)
+{
+ _MMCamcorderSubContext *sc = NULL;
+ mmf_camcorder_t *hcamcorder = NULL;
+ int index = 0;
+ const gchar *mime = NULL;
+ GstPad *sinkpad;
+ GstCaps *decsink_caps = NULL;
+ GstStructure *decsink_struct = NULL;
+
+ mmf_return_val_if_fail(handle, false);
+ mmf_return_val_if_fail(max_width, false);
+ mmf_return_val_if_fail(max_height, false);
+
+ hcamcorder = MMF_CAMCORDER(handle);
+ mmf_return_val_if_fail(hcamcorder, false);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+
+ sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst, "sink");
+ if (!sinkpad) {
+ _mmcam_dbg_err("There are no decoder caps");
+ return false;
+ }
+
+ decsink_caps = gst_pad_get_pad_template_caps(sinkpad);
+ if (!decsink_caps) {
+ gst_object_unref(sinkpad);
+ _mmcam_dbg_err("There is no decoder sink caps");
+ return false;
+ }
+
+ for (index = 0; index < gst_caps_get_size(decsink_caps); index++) {
+ decsink_struct = gst_caps_get_structure(decsink_caps, index);
+ if (!decsink_struct) {
+ _mmcam_dbg_err("There are no structure from caps");
+ gst_object_unref(decsink_caps);
+ gst_object_unref(sinkpad);
+ return false;
+ }
+ mime = gst_structure_get_name(decsink_struct);
+ if (!strcmp(mime, "video/x-h264")) {
+ _mmcam_dbg_log("h264 caps structure found");
+ if (gst_structure_has_field(decsink_struct, "maxwidth"))
+ *max_width = gst_value_get_int_range_max(gst_structure_get_value(decsink_struct, "maxwidth"));
+ if (gst_structure_has_field(decsink_struct, "maxheight"))
+ *max_height = gst_value_get_int_range_max(gst_structure_get_value(decsink_struct, "maxheight"));
+ break;
+ }
+ }
+ _mmcam_dbg_log("maxwidth = %d , maxheight = %d", (int)*max_width, (int)*max_height);
+ gst_object_unref(decsink_caps);
+ gst_object_unref(sinkpad);
+
+ if (*max_width <= 0 || *max_height <= 0)
+ return false;
+
+ return true;
+}
+#endif /* _MMCAMCORDER_PRODUCT_TV */