Add audio parse element and EOS packet to return 01/99601/5
authorjuan82.liu <juan82.liu@samsung.com>
Tue, 22 Nov 2016 23:23:34 +0000 (07:23 +0800)
committerGilbok Lee <gilbok.lee@samsung.com>
Mon, 28 Nov 2016 09:38:18 +0000 (18:38 +0900)
Change-Id: Id95b890213f079c2bfba0f4e81af756036a1a7ff

include/mediademuxer.h
include/port_gst/mediademuxer_port_gst.h
packaging/capi-mediademuxer.spec
src/port_gst/mediademuxer_port_gst.c

index 2810d7f..be38977 100755 (executable)
@@ -254,6 +254,7 @@ int mediademuxer_read_sample(mediademuxer_h demuxer, int track_index, media_pack
 /**
  * @brief Seeks to a particular instance of time (in milli seconds).
  * @since_tizen 3.0
+ * @remark If mediademuxer_seek() is followed by mediademuxer_read_sample(), outbuf will be the key frame right before the seek position.
  * @param[in] demuxer    The media demuxer handle
  * @param[in] pos       The value of the new start position
  * @return @c 0 on success, otherwise a negative error value
@@ -261,7 +262,7 @@ int mediademuxer_read_sample(mediademuxer_h demuxer, int track_index, media_pack
  * @retval #MEDIADEMUXER_ERROR_INVALID_PARAMETER Invalid parameter
  * @retval #MEDIADEMUXER_ERROR_INVALID_STATE Invalid state
  * @retval #MEDIADEMUXER_ERROR_INVALID_OPERATION Invalid Operation
-* @pre The media demuxer state should be #MEDIADEMUXER_STATE_DEMUXING.
+ * @pre The media demuxer state should be #MEDIADEMUXER_STATE_DEMUXING.
  * @see mediademuxer_read_sample()
  * @see mediademuxer_stop()
  * */
index 8bda13a..80865ff 100755 (executable)
@@ -60,6 +60,7 @@ typedef enum {
 typedef struct track {
        GstPad *pad;
        GstCaps *caps;
+       bool need_codec_data;
        gchar *name;
        gchar *caps_string;
        GstElement *appsink;
index 36eed02..1fdb02c 100755 (executable)
@@ -1,6 +1,6 @@
 Name:       capi-mediademuxer
 Summary:    A Media Demuxer library in Tizen Native API
-Version:    0.1.9
+Version:    0.1.10
 Release:    1
 Group:      Multimedia/API
 License:    Apache-2.0
index e5aa061..32ea0da 100755 (executable)
@@ -237,6 +237,7 @@ int __gst_add_track_info(GstPad *pad, gchar *name, track **head,
        temp->caps_string = gst_caps_to_string(temp->caps);
        temp->next = NULL;
        temp->format = NULL;
+       temp->need_codec_data = TRUE;
 
        /* Link demuxer - queue */
        temp->queue = gst_element_factory_make("queue", NULL);
@@ -285,54 +286,79 @@ int __gst_add_track_info(GstPad *pad, gchar *name, track **head,
                goto ERROR;
        }
        /* Check for type video and it should be h264 */
-       if (strstr(name, "video") && strstr(temp->caps_string, "h264")) {
-               parse_element = gst_element_factory_make("h264parse", NULL);
-               if (!parse_element) {
-                       MD_E("factory not able to make h264parse");
-                       goto ERROR;
-               }
-               if (!gst_bin_add(GST_BIN(pipeline), parse_element)) {
-                       MD_E("fail add h264parse in pipeline");
-                       goto ERROR;
-               }
-               parse_sink_pad = gst_element_get_static_pad(parse_element, "sink");
-               if (!parse_sink_pad) {
-                       gst_object_unref(parse_element);
-                       MD_E("sink pad of h264parse not available");
-                       goto ERROR;
+       if (strstr(name, "video")) {
+               if (strstr(temp->caps_string, "h264")) {
+                       parse_element = gst_element_factory_make("h264parse", NULL);
+                       if (!parse_element) {
+                               MD_E("factory not able to make h264parse");
+                               goto ERROR;
+                       }
+               } else if(strstr(temp->caps_string, "mpeg")) {
+                       parse_element = gst_element_factory_make("mpeg4videoparse", NULL);
+                       if (!parse_element) {
+                               MD_E("factory not able to make h264parse");
+                               goto ERROR;
+                       }
+                       g_object_set(G_OBJECT(parse_element), "config-interval", 1, NULL);
                }
 
-               MEDIADEMUXER_SET_STATE(parse_element, GST_STATE_PAUSED, ERROR);
-
-               /* Link demuxer pad with sink pad of parse element */
-               MEDIADEMUXER_LINK_PAD(queue_src_pad, parse_sink_pad, ERROR);
-
-               outcaps = gst_caps_new_simple("video/x-h264", "stream-format", G_TYPE_STRING, "byte-stream", NULL);
-               gst_element_link_filtered(parse_element, temp->appsink, outcaps);
-               gst_caps_unref(outcaps);
-       } else if (strstr(name, "video") && strstr(temp->caps_string, "mpeg")) {
-               parse_element = gst_element_factory_make("mpeg4videoparse", NULL);
-               if (!parse_element) {
-                       MD_E("factory not able to make mpeg4videoparse");
-                       goto ERROR;
+               if(parse_element) {
+                       gst_bin_add(GST_BIN(pipeline), parse_element);
+                       parse_sink_pad = gst_element_get_static_pad(parse_element, "sink");
+                       if (!parse_sink_pad) {
+                               gst_object_unref(parse_element);
+                               MD_E("sink pad of h264parse not available");
+                               goto ERROR;
+                       }
+                       MEDIADEMUXER_SET_STATE(parse_element, GST_STATE_PAUSED, ERROR);
+                       /* Link demuxer pad with sink pad of parse element */
+                       MEDIADEMUXER_LINK_PAD(queue_src_pad, parse_sink_pad, ERROR);
+
+                       if (strstr(temp->caps_string, "h264")) {
+                               outcaps = gst_caps_new_simple("video/x-h264", "stream-format", G_TYPE_STRING, "byte-stream", NULL);
+                               gst_element_link_filtered(parse_element, temp->appsink, outcaps);
+                               gst_caps_unref(outcaps);
+                       } else if (strstr(temp->caps_string, "mpeg")) {
+                               gst_element_link(parse_element, temp->appsink);
+                       } else {
+                               MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
+                       }
                }
-               if (!gst_bin_add(GST_BIN(pipeline), parse_element)) {
-                       MD_E("fail add mpeg4videoparse in pipeline");
-                       goto ERROR;
+       } else if(strstr(name, "audio")) {
+               //Create Parse
+               if (strstr(temp->caps_string, "audio/mpeg")) {
+                       int mpegversion = 0;
+                       GstStructure *structure = NULL;
+                       structure = gst_caps_get_structure(temp->caps, 0);
+                       gst_structure_get_int (structure, "mpegversion", &mpegversion);
+                       if(mpegversion == 2 || mpegversion == 4)
+                               parse_element = gst_element_factory_make("aacparse", NULL);
+                       else if(mpegversion == 1)
+                               parse_element = gst_element_factory_make("mpegaudioparse", NULL);
+               } else if (strstr(temp->caps_string, "application/x-id3")) {
+                       parse_element = gst_element_factory_make("mpegaudioparse", NULL);
+               } else if (strstr(temp->caps_string, "audio/x-amr-nb-sh")
+                               || strstr(temp->caps_string, "audio/x-amr-wb-sh")) {
+                       parse_element = gst_element_factory_make("amrparse", NULL);
+               } else if (strstr(temp->caps_string, "audio/x-wav")) {
+                       parse_element = gst_element_factory_make("wavparse", NULL);
+               } else if (strstr(temp->caps_string, "audio/x-flac")) {
+                       parse_element = gst_element_factory_make("flacparse", NULL);
                }
+
+               gst_bin_add(GST_BIN(pipeline), parse_element);
                parse_sink_pad = gst_element_get_static_pad(parse_element, "sink");
                if (!parse_sink_pad) {
                        gst_object_unref(parse_element);
-                       MD_E("sink pad of mpeg4videoparse not available");
+                       MD_E("sink pad of h264parse not available");
                        goto ERROR;
                }
-
-               g_object_set(G_OBJECT(parse_element), "config-interval", 1, NULL);
-
                MEDIADEMUXER_SET_STATE(parse_element, GST_STATE_PAUSED, ERROR);
 
                /* Link demuxer pad with sink pad of parse element */
                MEDIADEMUXER_LINK_PAD(queue_src_pad, parse_sink_pad, ERROR);
+
+               /* Link src pad with appSink element */
                gst_element_link(parse_element, temp->appsink);
        } else {
                MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
@@ -358,6 +384,8 @@ int __gst_add_track_info(GstPad *pad, gchar *name, track **head,
        return MD_ERROR_NONE;
 
 ERROR:
+       if (parse_element)
+               gst_object_unref(parse_element);
        if (temp->caps)
                gst_object_unref(temp->caps);
        if (temp->caps_string)
@@ -428,18 +456,18 @@ static int __gst_create_audio_only_pipeline(gpointer data,  GstCaps *caps)
        mdgst_handle_t *gst_handle = (mdgst_handle_t *) data;
        GstPad *pad = NULL;
        GstPad *aud_pad = NULL;
-       GstPad *queue_srcpad = NULL;
-       GstPad *queue_sinkpad = NULL;
        GstPad *aud_srcpad = NULL;
        GstPad *fake_pad = NULL;
        GstElement *id3tag = NULL;
-       GstElement *adif_queue = NULL;
-       gchar *name;
-       gchar *type;
+       gchar *name = NULL;
+       gchar *type = NULL;
        track_info *head_track = &(gst_handle->info);
-       track *trck;
+       track *trck = NULL;
+
        gst_handle->is_valid_container = true;
+
        type = gst_caps_to_string(caps);
+
        if (strstr(type, "adts") || strstr(type, "adif")) {
                gst_handle->demux = gst_element_factory_make("aacparse", NULL);
        } else if (strstr(type, "audio/mpeg")) {
@@ -468,6 +496,17 @@ static int __gst_create_audio_only_pipeline(gpointer data,  GstCaps *caps)
                        MD_E("fail to get typefind src pad.\n");
                        goto ERROR;
                }
+
+               fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
+               if (!fake_pad) {
+                       MD_E("fail to get fakesink sink pad.\n");
+                       goto ERROR;
+               }
+               gst_pad_unlink(pad, fake_pad);
+
+               if (fake_pad)
+                       gst_object_unref(fake_pad);
+
                if (!id3tag)
                        aud_pad = gst_element_get_static_pad(gst_handle->demux, "sink");
                else
@@ -476,33 +515,32 @@ static int __gst_create_audio_only_pipeline(gpointer data,  GstCaps *caps)
                        MD_E("fail to get audio parse sink pad.\n");
                        goto ERROR;
                }
-               fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
-               if (!fake_pad) {
-                       MD_E("fail to get fakesink sink pad.\n");
-                       goto ERROR;
-               }
-               gst_pad_unlink(pad, fake_pad);
+
+               MEDIADEMUXER_LINK_PAD(pad, aud_pad, ERROR);
+               if (pad)
+                       gst_object_unref(pad);
+               if (aud_pad)
+                       gst_object_unref(aud_pad);
+
                if (!id3tag) {
-                       MEDIADEMUXER_SET_STATE(gst_handle->demux,
-                                              GST_STATE_PAUSED, ERROR);
+                       MEDIADEMUXER_SET_STATE(gst_handle->demux, GST_STATE_PAUSED, ERROR);
                } else {
                        MEDIADEMUXER_SET_STATE(id3tag, GST_STATE_PAUSED, ERROR);
-                       MEDIADEMUXER_SET_STATE(gst_handle->demux,
-                                              GST_STATE_PAUSED, ERROR);
+                       MEDIADEMUXER_SET_STATE(gst_handle->demux, GST_STATE_PAUSED, ERROR);
                        gst_element_link(id3tag, gst_handle->demux);
                }
        }
 
-       /* calling "on_pad_added" function to set the caps */
+       gst_handle->total_tracks++;
+
        aud_srcpad = gst_element_get_static_pad(gst_handle->demux, "src");
        if (!aud_srcpad) {
                MD_E("fail to get audioparse source pad.\n");
                goto ERROR;
        }
-       gst_handle->total_tracks++;
+
        name = gst_pad_get_name(aud_srcpad);
-       if (__gst_add_track_info(aud_srcpad, name, &(head_track->head), gst_handle->pipeline)
-           != MD_ERROR_NONE) {
+       if (__gst_add_track_info(aud_srcpad, name, &(head_track->head), gst_handle->pipeline) != MD_ERROR_NONE) {
                MD_E("unable to added track info");
                head_track->num_audio_track = 0;
                head_track->num_video_track = 0;
@@ -511,33 +549,6 @@ static int __gst_create_audio_only_pipeline(gpointer data,  GstCaps *caps)
                __gst_free_stuct(&(head_track->head));
                goto ERROR;
        }
-       if (strstr(type, "adif")) {
-               adif_queue = gst_element_factory_make("queue", NULL);
-               if (!adif_queue) {
-                       MD_E("factory not able to make queue in case of adif aac\n");
-                       goto ERROR;
-               }
-               /* Add this queue to the pipeline */
-               gst_bin_add_many(GST_BIN(gst_handle->pipeline), adif_queue, NULL);
-               queue_srcpad = gst_element_get_static_pad(adif_queue, "src");
-               if (!queue_srcpad) {
-                       MD_E("fail to get queue src pad for adif aac.\n");
-                       goto ERROR;
-               }
-               queue_sinkpad = gst_element_get_static_pad(adif_queue, "sink");
-               if (!queue_sinkpad) {
-                       MD_E("fail to get queue sink pad for adif aac.\n");
-                       goto ERROR;
-               }
-               /* link typefind with queue */
-               MEDIADEMUXER_LINK_PAD(pad, queue_sinkpad, ERROR);
-               /* link queue with aacparse */
-               MEDIADEMUXER_LINK_PAD(queue_srcpad, aud_pad, ERROR);
-       } else {
-               MEDIADEMUXER_LINK_PAD(pad, aud_pad, ERROR);
-       }
-       if (adif_queue)
-               MEDIADEMUXER_SET_STATE(adif_queue, GST_STATE_PAUSED, ERROR);
 
        trck = head_track->head;
        while (trck != NULL && aud_srcpad != trck->pad)
@@ -546,7 +557,7 @@ static int __gst_create_audio_only_pipeline(gpointer data,  GstCaps *caps)
        if (trck != NULL) {
                if (trck->caps)
                        gst_caps_unref(trck->caps);
-               trck->caps = caps;
+               trck->caps = gst_caps_copy(caps);
                if (trck->caps_string)
                        g_free(trck->caps_string);
                trck->caps_string = gst_caps_to_string(trck->caps);
@@ -556,19 +567,10 @@ static int __gst_create_audio_only_pipeline(gpointer data,  GstCaps *caps)
                g_strlcpy(name, "audio", strlen(name));
                trck->name = name;
        }
+
        (head_track->num_audio_track)++;
 
        /* unref pads */
-       if (pad)
-               gst_object_unref(pad);
-       if (aud_pad)
-               gst_object_unref(aud_pad);
-       if (fake_pad)
-               gst_object_unref(fake_pad);
-       if (queue_sinkpad)
-               gst_object_unref(queue_sinkpad);
-       if (queue_srcpad)
-               gst_object_unref(queue_srcpad);
        if (aud_srcpad)
                gst_object_unref(aud_srcpad);
 
@@ -576,6 +578,7 @@ static int __gst_create_audio_only_pipeline(gpointer data,  GstCaps *caps)
        g_free(type);
        MEDIADEMUXER_FLEAVE();
        return MD_ERROR_NONE;
+
 ERROR:
        gst_handle->is_valid_container = false;
        if (gst_handle->demux)
@@ -588,10 +591,7 @@ ERROR:
                gst_object_unref(fake_pad);
        if (aud_srcpad)
                gst_object_unref(aud_srcpad);
-       if (queue_sinkpad)
-               gst_object_unref(queue_sinkpad);
-       if (queue_srcpad)
-               gst_object_unref(queue_srcpad);
+
        g_free(type);
        MEDIADEMUXER_FLEAVE();
        return MD_ERROR;
@@ -1268,6 +1268,10 @@ static int _gst_copy_buf_to_media_packet(media_packet_h out_pkt,
                        goto ERROR;
                }
                gst_buffer_unmap(codec_data, &codec_data_map);
+
+               media_buffer_flags_e flags;
+               media_packet_get_flags(out_pkt, &flags);
+               media_packet_set_flags(out_pkt, flags | MEDIA_PACKET_CODEC_CONFIG);
        }
 ERROR:
        gst_buffer_unmap(buffer, &map);
@@ -1275,6 +1279,36 @@ ERROR:
        return ret;
 }
 
+static int _gst_demuxer_create_eos_packet(media_format_h fmt, media_packet_h *outbuf)
+{
+       media_packet_h mediabuf = NULL;
+       int ret = MD_ERROR_NONE;
+
+       MEDIADEMUXER_FENTER();
+       if (media_packet_create_alloc(fmt, NULL, NULL, &mediabuf)) {
+               MD_E("media_packet_create_alloc failed\n");
+               ret = MD_ERROR;
+               goto ERROR;
+       }
+
+       if (media_packet_set_flags(mediabuf, MEDIA_PACKET_END_OF_STREAM)) {
+               MD_E("unable to set EOS flag\n");
+               ret = MD_ERROR_UNKNOWN;
+               goto ERROR;
+       }
+
+       *outbuf = mediabuf;
+       MEDIADEMUXER_FLEAVE();
+
+       return ret;
+       ERROR:
+       if (mediabuf)
+               media_packet_destroy(mediabuf);
+       *outbuf = NULL;
+       MEDIADEMUXER_FLEAVE();
+       return ret;
+}
+
 static int gst_demuxer_read_sample(MMHandleType pHandle,
                                                media_packet_h *outbuf, int track_indx)
 {
@@ -1326,6 +1360,9 @@ static int gst_demuxer_read_sample(MMHandleType pHandle,
                        ret = MD_ERROR_NONE;
                        *outbuf = NULL;
                        __gst_eos_callback(track_indx, demuxer);
+
+                       //Make EOS packet
+                       _gst_demuxer_create_eos_packet(atrack->format, outbuf);
                        return ret;
                } else {
                        MD_E("gst_demuxer_read_sample failed\n");
@@ -1348,14 +1385,20 @@ static int gst_demuxer_read_sample(MMHandleType pHandle,
                goto ERROR;
        }
 
-       /* Create the codec data and pass to _gst_copy_buf_to_media_packet() to add into the media packet */
-       GstStructure *structure = NULL;
-       const GValue *value = NULL;
        GstBuffer *codec_data_buffer = NULL;
-       structure = gst_caps_get_structure(atrack->caps, 0);
-       value = gst_structure_get_value(structure, "codec_data");
-       if (value)
-               codec_data_buffer = gst_value_get_buffer(value);
+       /* Need to Check : Only the first frame need set codec_data, what about Resolution changed instance ...*/
+       if (atrack->need_codec_data) {
+               atrack->need_codec_data = FALSE;
+               /* Create the codec data and pass to _gst_copy_buf_to_media_packet() to add into the media packet */
+               GstStructure *structure = NULL;
+               const GValue *value = NULL;
+
+               structure = gst_caps_get_structure(atrack->caps, 0);
+               /* get codec data from caps*/
+               value = gst_structure_get_value(structure, "codec_data");
+               if (value)
+                       codec_data_buffer = gst_value_get_buffer(value);
+       }
 
        /* Fill the media_packet with proper information */
        ret = _gst_copy_buf_to_media_packet(mediabuf, buffer, codec_data_buffer);
@@ -1413,6 +1456,7 @@ static int gst_demuxer_seek(MMHandleType pHandle, gint64 pos1)
        while (temp) {
                MD_I("Got one element %p\n", temp->appsink);
                if (gst_handle->selected_tracks[indx] == true) {
+                       temp->need_codec_data = TRUE;
                        if (!gst_element_seek(temp->appsink, rate, GST_FORMAT_TIME,
                             GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_BEFORE,
                             GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {