From: Jeongmo Yang Date: Thu, 1 Sep 2022 09:06:30 +0000 (+0900) Subject: Support H.264 video recording on RB5 X-Git-Tag: accepted/tizen/unified/20220904.214042^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8aa322d38824e531de5cfe71853ca45da93efce4;p=platform%2Fcore%2Fmultimedia%2Flibmm-camcorder.git Support H.264 video recording on RB5 [Version] 0.10.268 [Issue Type] Improvement Change-Id: I3966d064ceeb1cd173706eb485f525276a85ecf4 Signed-off-by: Jeongmo Yang --- diff --git a/packaging/libmm-camcorder.spec b/packaging/libmm-camcorder.spec index 0172819..48801a5 100755 --- a/packaging/libmm-camcorder.spec +++ b/packaging/libmm-camcorder.spec @@ -1,6 +1,6 @@ Name: libmm-camcorder Summary: Camera and recorder library -Version: 0.10.267 +Version: 0.10.268 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/include/mm_camcorder_internal.h b/src/include/mm_camcorder_internal.h index cbca186..c51ef04 100644 --- a/src/include/mm_camcorder_internal.h +++ b/src/include/mm_camcorder_internal.h @@ -540,6 +540,7 @@ typedef enum { _MMCAMCORDER_VIDEOSRC_SRC, _MMCAMCORDER_VIDEOSRC_FILT, _MMCAMCORDER_VIDEOSRC_QUE, + _MMCAMCORDER_VIDEOSRC_PARSE, _MMCAMCORDER_VIDEOSRC_DECODE, /* Pipeline element of image capture */ diff --git a/src/mm_camcorder_gstcommon.c b/src/mm_camcorder_gstcommon.c index 44e7a84..1c9a76d 100644 --- a/src/mm_camcorder_gstcommon.c +++ b/src/mm_camcorder_gstcommon.c @@ -129,6 +129,7 @@ static gboolean videocodec_fileformat_compatibility_table[MM_VIDEO_CODEC_NUM][MM #define _MMCAMCORDER_CONVERT_OUTPUT_BUFFER_NUM 6 #define _MMCAMCORDER_NANOSEC_PER_1SEC 1000000000 #define _MMCAMCORDER_NANOSEC_PER_1MILISEC 1000 +#define _MMCAMCORDER_SIGNAL_REQUEST_CODEC_CONFIG "request-codec-config" /*----------------------------------------------------------------------- @@ -151,13 +152,15 @@ static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstP static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data); static int __mmcamcorder_get_amrnb_bitrate_mode(int bitrate); -static guint32 _mmcamcorder_convert_fourcc_string_to_value(const gchar* format_name); +static guint32 _mmcamcorder_get_structure_fourcc(const GstStructure *structure); #ifdef _MMCAMCORDER_PRODUCT_TV static bool __mmcamcorder_find_max_resolution(MMHandleType handle, gint *max_width, gint *max_height); #endif /* _MMCAMCORDER_PRODUCT_TV */ static gboolean __mmcamcorder_set_stream_data(MMCamcorderVideoStreamDataType *stream, GstBuffer *buffer, GstMapInfo *map_info); static gboolean __mmcamcorder_set_stream_data_zero_copy(MMCamcorderVideoStreamDataType *stream, GstBuffer *buffer, GstMemory *memory); +static const char *__mmcamcorder_get_parser_name(MMPixelFormatType format); +static void __mmcamcorder_request_codec_config(GstElement *videosrc_element); /*======================================================================================= | FUNCTION DEFINITIONS | @@ -374,6 +377,39 @@ static gboolean __mmcamcorder_set_stream_data_zero_copy(MMCamcorderVideoStreamDa } +static const char *__mmcamcorder_get_parser_name(MMPixelFormatType format) +{ + switch (format) { + case MM_PIXEL_FORMAT_ENCODED_H264: + return "h264parse"; + case MM_PIXEL_FORMAT_ENCODED_VP9: + return "vp9parse"; + default: + MMCAM_LOG_WARNING("unsupported format[%d]", format); + return NULL; + } +} + + +static void __mmcamcorder_request_codec_config(GstElement *videosrc_element) +{ + if (!videosrc_element || !G_TYPE_CHECK_INSTANCE(videosrc_element)) { + MMCAM_LOG_WARNING("invalid videosrc element[%p]", videosrc_element); + return; + } + + if (!g_signal_parse_name(_MMCAMCORDER_SIGNAL_REQUEST_CODEC_CONFIG, + G_TYPE_FROM_INSTANCE(videosrc_element), NULL, NULL, FALSE)) { + MMCAM_LOG_WARNING("no signal[%s]", _MMCAMCORDER_SIGNAL_REQUEST_CODEC_CONFIG); + return; + } + + MMCAM_LOG_INFO("emit signal[%s]", _MMCAMCORDER_SIGNAL_REQUEST_CODEC_CONFIG); + + g_signal_emit_by_name(videosrc_element, _MMCAMCORDER_SIGNAL_REQUEST_CODEC_CONFIG); +} + + gboolean _mmcamcorder_invoke_video_stream_cb(MMHandleType handle, GstSample *sample, gboolean is_preview, int stream_id) { int i = 0; @@ -418,7 +454,7 @@ gboolean _mmcamcorder_invoke_video_stream_cb(MMHandleType handle, GstSample *sam } structure = gst_mini_object_get_qdata(GST_MINI_OBJECT_CAST(buffer), hcamcorder->buffer_quark); - if (structure) { + if (structure && gst_structure_has_field(structure, "focus-state")) { gst_structure_get(structure, "focus-state", G_TYPE_INT, &stream.focus_state, "facing-direction", G_TYPE_INT, &stream.facing_direction, @@ -496,6 +532,7 @@ int _mmcamcorder_create_preview_elements(MMHandleType handle) const char *videosink_name = NULL; const char *videoconvert_name = NULL; const char *videodecoder_name = NULL; + const char *videoparse_name = NULL; const char *decoder_conf_name = NULL; char videodecoder_name_final[32] = {'\0',}; char *err_name = NULL; @@ -710,6 +747,10 @@ int _mmcamcorder_create_preview_elements(MMHandleType handle) } #endif /* _MMCAMCORDER_RM_SUPPORT */ + videoparse_name = __mmcamcorder_get_parser_name(sc->info_image->preview_format); + if (videoparse_name) + _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSRC_PARSE, videoparse_name, "videosrc_parse", element_list, err); + _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSRC_DECODE, videodecoder_name_final, "videosrc_decode", element_list, err); _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst, sc->VideodecoderElement); @@ -1364,8 +1405,10 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin } if (_mmcamcorder_is_encoded_preview_pixel_format(sc->info_image->preview_format)) { - /* set dummy element */ - gst_element_venc_name = "identity"; + /* set parse element */ + gst_element_venc_name = __mmcamcorder_get_parser_name(sc->info_image->preview_format); + if (!gst_element_venc_name) + gst_element_venc_name = "identity"; } else { _mmcamcorder_conf_get_value_element_name(VideoencElement, &gst_element_venc_name); } @@ -1728,7 +1771,8 @@ void _mmcamcorder_ready_to_encode_callback(GstElement *element, guint size, gpoi /* set flag */ if (sc->info_video->push_encoding_buffer == PUSH_ENCODING_BUFFER_INIT) { sc->info_video->push_encoding_buffer = PUSH_ENCODING_BUFFER_RUN; - MMCAM_LOG_WARNING("set push_encoding_buffer RUN"); + __mmcamcorder_request_codec_config(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); + MMCAM_LOG_WARNING("start to push buffer to encoding pipeline"); } } @@ -1996,9 +2040,37 @@ gboolean _mmcamcorder_get_device_info(MMHandleType handle) return TRUE; } -static guint32 _mmcamcorder_convert_fourcc_string_to_value(const gchar* format_name) +static guint32 _mmcamcorder_get_structure_fourcc(const GstStructure *structure) { - return format_name[0] | (format_name[1] << 8) | (format_name[2] << 16) | (format_name[3] << 24); + const gchar *format_string = NULL; + + if (!structure) { + MMCAM_LOG_WARNING("NULL structure"); + return GST_MAKE_FOURCC('N', 'U', 'L', 'L'); + } + + if (gst_structure_has_name(structure, "video/x-h264")) + return GST_MAKE_FOURCC('H', '2', '6', '4'); + + if (gst_structure_has_name(structure, "video/x-h265")) + return GST_MAKE_FOURCC('H', '2', '6', '5'); + + if (gst_structure_has_name(structure, "video/x-vp8")) + return GST_MAKE_FOURCC('V', 'P', '8', '0'); + + if (gst_structure_has_name(structure, "video/x-vp9")) + return GST_MAKE_FOURCC('V', 'P', '9', '0'); + + if (gst_structure_has_name(structure, "video/x-jpeg") || + gst_structure_has_name(structure, "image/jpeg")) + return GST_MAKE_FOURCC('M', 'J', 'P', 'G'); + + format_string = gst_structure_get_string(structure, "format"); + + if (format_string) + return GST_STR_FOURCC(format_string); + + return GST_MAKE_FOURCC('N', 'O', 'N', 'E'); } static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstPadProbeInfo *info, gpointer u_data) @@ -2645,44 +2717,42 @@ bool _mmcamcorder_set_videosrc_caps(MMHandleType handle, unsigned int fourcc, in structure = gst_caps_get_structure(caps, 0); if (structure) { - const gchar *format_string = NULL; int caps_width = 0; int caps_height = 0; - int caps_fps = 0; + int caps_fps_n = 0; + int caps_fps_d = 0; int caps_rotate = 0; - format_string = gst_structure_get_string(structure, "format"); - if (format_string) - caps_fourcc = _mmcamcorder_convert_fourcc_string_to_value(format_string); + caps_fourcc = _mmcamcorder_get_structure_fourcc(structure); gst_structure_get(structure, "width", G_TYPE_INT, &caps_width, "height", G_TYPE_INT, &caps_height, - "fps", G_TYPE_INT, &caps_fps, + "framerate", GST_TYPE_FRACTION, &caps_fps_n, &caps_fps_d, "rotate", G_TYPE_INT, &caps_rotate, NULL); #ifdef _MMCAMCORDER_PRODUCT_TV if (_mmcamcorder_is_encoded_preview_pixel_format(sc->info_image->preview_format)) { if (set_width == caps_width && set_height == caps_height && - set_rotate == caps_rotate && fps == caps_fps) { + set_rotate == caps_rotate && fps == caps_fps_n) { MMCAM_LOG_INFO("No need to replace caps."); } else { - MMCAM_LOG_INFO("current [%c%c%c%c %dx%d, fps %d, rot %d], new [%c%c%c%c %dx%d, fps %d, rot %d]", + MMCAM_LOG_INFO("current [%c%c%c%c %dx%d, fps %d/%d, rot %d], new [%c%c%c%c %dx%d, fps %d, rot %d]", caps_fourcc, caps_fourcc>>8, caps_fourcc>>16, caps_fourcc>>24, - caps_width, caps_height, caps_fps, caps_rotate, + caps_width, caps_height, caps_fps_n, caps_fps_d, caps_rotate, fourcc, fourcc>>8, fourcc>>16, fourcc>>24, set_width, set_height, fps, set_rotate); do_set_caps = TRUE; } } else { if (set_width == caps_width && set_height == caps_height && - fourcc == caps_fourcc && set_rotate == caps_rotate && fps == caps_fps) { + fourcc == caps_fourcc && set_rotate == caps_rotate && fps == caps_fps_n) { MMCAM_LOG_INFO("No need to replace caps."); } else { - MMCAM_LOG_INFO("current [%c%c%c%c %dx%d, fps %d, rot %d], new [%c%c%c%c %dx%d, fps %d, rot %d]", + MMCAM_LOG_INFO("current [%c%c%c%c %dx%d, fps %d/%d, rot %d], new [%c%c%c%c %dx%d, fps %d, rot %d]", caps_fourcc, caps_fourcc>>8, caps_fourcc>>16, caps_fourcc>>24, - caps_width, caps_height, caps_fps, caps_rotate, + caps_width, caps_height, caps_fps_n, caps_fps_d, caps_rotate, fourcc, fourcc>>8, fourcc>>16, fourcc>>24, set_width, set_height, fps, set_rotate); do_set_caps = TRUE; @@ -2690,12 +2760,12 @@ bool _mmcamcorder_set_videosrc_caps(MMHandleType handle, unsigned int fourcc, in } #else /*_MMCAMCORDER_PRODUCT_TV */ if (set_width == caps_width && set_height == caps_height && - fourcc == caps_fourcc && set_rotate == caps_rotate && fps == caps_fps) { + fourcc == caps_fourcc && set_rotate == caps_rotate && fps == caps_fps_n) { MMCAM_LOG_INFO("No need to replace caps."); } else { - MMCAM_LOG_INFO("current [%c%c%c%c %dx%d, fps %d, rot %d], new [%c%c%c%c %dx%d, fps %d, rot %d]", + MMCAM_LOG_INFO("current [%c%c%c%c %dx%d, fps %d/%d, rot %d], new [%c%c%c%c %dx%d, fps %d, rot %d]", caps_fourcc, caps_fourcc>>8, caps_fourcc>>16, caps_fourcc>>24, - caps_width, caps_height, caps_fps, caps_rotate, + caps_width, caps_height, caps_fps_n, caps_fps_d, caps_rotate, fourcc, fourcc>>8, fourcc>>16, fourcc>>24, set_width, set_height, fps, set_rotate); do_set_caps = TRUE; diff --git a/src/mm_camcorder_videorec.c b/src/mm_camcorder_videorec.c index 3ee2402..ec55f69 100644 --- a/src/mm_camcorder_videorec.c +++ b/src/mm_camcorder_videorec.c @@ -91,20 +91,20 @@ gboolean _mmcamcorder_video_push_buffer(void *handle, GstSample *sample) int ret = 0; GstClock *clock = NULL; - MMCAM_LOG_VERBOSE("GST_BUFFER_FLAG_DELTA_UNIT is set : %d", - GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT)); + MMCAM_LOG_VERBOSE("buffer[%p] - delta flag[%d]", + buffer, GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT)); current_ts = GST_BUFFER_PTS(buffer); if (info_video->is_first_frame) { /* check first I frame for H.264 stream */ if (_mmcamcorder_is_encoded_preview_pixel_format(info_image->preview_format)) { - if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT)) { - MMCAM_LOG_WARNING("NOT key frame.. skip this buffer"); + if (GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_HEADER)) { + MMCAM_LOG_WARNING("No header in buffer"); return TRUE; - } else { - MMCAM_LOG_WARNING("first key frame"); } + + MMCAM_LOG_WARNING("Got buffer with header"); } /* set base timestamp */ @@ -139,7 +139,7 @@ gboolean _mmcamcorder_video_push_buffer(void *handle, GstSample *sample) GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer) = current_ts - info_video->base_video_ts; - MMCAM_LOG_DEBUG("buffer %p, timestamp %"GST_TIME_FORMAT, + MMCAM_LOG_DEBUG("buffer[%p] - timestamp[%"GST_TIME_FORMAT"]", buffer, GST_TIME_ARGS(GST_BUFFER_PTS(buffer))); /* It will INCREASE reference count of buffer */