diff --git a/generic-pc/playback_gst_10.cpp b/generic-pc/playback_gst_10.cpp index f7c0f3d..08bc508 100644 --- a/generic-pc/playback_gst_10.cpp +++ b/generic-pc/playback_gst_10.cpp @@ -71,9 +71,10 @@ typedef enum GstElement * m_gst_playbin = NULL; GstElement * audioSink = NULL; GstElement * videoSink = NULL; - gchar * uri = NULL; GstTagList * m_stream_tags = NULL; +pthread_mutex_t mutex_tag_ist; + static int end_eof = 0; #define HTTP_TIMEOUT 30 // taken from record.h @@ -112,7 +113,7 @@ void processMpegTsSection(GstMpegtsSection* section) } } -void playbinNotifySource(GObject *object, GParamSpec *unused, gpointer user_data) +void playbinNotifySource(GObject *object, GParamSpec *param_spec, gpointer user_data) { GstElement *source = NULL; cPlayback *_this = (cPlayback*)user_data; @@ -190,10 +191,8 @@ void playbinNotifySource(GObject *object, GParamSpec *unused, gpointer user_data } } -GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) +GstBusSyncReply Gst_bus_call(GstBus *bus, GstMessage *msg, gpointer user_data) { - gchar * sourceName; - // source GstObject * source; source = GST_MESSAGE_SRC(msg); @@ -201,8 +200,6 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) if (!GST_IS_OBJECT(source)) return GST_BUS_DROP; - sourceName = gst_object_get_name(source); - switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_EOS: @@ -218,6 +215,7 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) GError *err; gst_message_parse_error(msg, &err, &debug); g_free (debug); + gchar * sourceName = gst_object_get_name(source); lt_info_c( "%s:%s - GST_MESSAGE_ERROR: %s (%i) from %s\n", FILENAME, __FUNCTION__, err->message, err->code, sourceName ); if ( err->domain == GST_STREAM_ERROR ) { @@ -230,6 +228,8 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) } } g_error_free(err); + if(sourceName) + g_free(sourceName); end_eof = 1; // NOTE: just to exit @@ -245,8 +245,12 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) g_free (debug); if ( inf->domain == GST_STREAM_ERROR && inf->code == GST_STREAM_ERROR_DECODE ) { + gchar * sourceName = gst_object_get_name(source); if ( g_strrstr(sourceName, "videosink") ) lt_info_c( "%s:%s - GST_MESSAGE_INFO: videosink\n", FILENAME, __FUNCTION__ ); //FIXME: how shall playback handle this event??? + if(sourceName) + g_free(sourceName); + } g_error_free(inf); break; @@ -254,9 +258,16 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) case GST_MESSAGE_TAG: { - GstTagList *tags, *result; + GstTagList *tags = NULL, *result = NULL; gst_message_parse_tag(msg, &tags); + if(tags == NULL) + break; + if(!GST_IS_TAG_LIST(tags)) + break; + + pthread_mutex_lock (&mutex_tag_ist); + result = gst_tag_list_merge(m_stream_tags, tags, GST_TAG_MERGE_REPLACE); if (result) { @@ -264,6 +275,8 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) { gst_tag_list_unref(tags); gst_tag_list_unref(result); + + pthread_mutex_unlock (&mutex_tag_ist); break; } if (m_stream_tags) @@ -272,6 +285,8 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) gst_tag_list_unref(result); } + pthread_mutex_unlock (&mutex_tag_ist); + const GValue *gv_image = gst_tag_list_get_value_index(tags, GST_TAG_IMAGE, 0); if ( gv_image ) { @@ -294,7 +309,8 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) lt_info_c("%s:%s - /tmp/.id3coverart %d bytes written\n", FILENAME, __FUNCTION__, ret); } } - gst_tag_list_unref(tags); + if (tags) + gst_tag_list_unref(tags); lt_debug_c( "%s:%s - GST_MESSAGE_INFO: update info tags\n", FILENAME, __FUNCTION__); //FIXME: how shall playback handle this event??? break; } @@ -341,7 +357,7 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) case GST_STATE_CHANGE_READY_TO_PAUSED: { GstIterator *children; - GValue r = { 0, }; + GValue r = G_VALUE_INIT; if (audioSink) { @@ -355,8 +371,7 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) videoSink = NULL; } children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin)); - - if (gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBAudioSink")) + if (children && gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBAudioSink")) { audioSink = GST_ELEMENT_CAST(g_value_dup_object (&r)); g_value_unset (&r); @@ -365,8 +380,7 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data) gst_iterator_free(children); children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin)); - - if (gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBVideoSink")) + if (children && gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBVideoSink")) { videoSink = GST_ELEMENT_CAST(g_value_dup_object (&r)); g_value_unset (&r); @@ -421,6 +435,10 @@ cPlayback::cPlayback(int num) gst_version (&major, &minor, µ, &nano); + gst_mpegts_initialize(); + + pthread_mutex_init (&mutex_tag_ist, NULL); + if (nano == 1) nano_str = "(CVS)"; else if (nano == 2) @@ -445,8 +463,10 @@ cPlayback::~cPlayback() { lt_info( "%s:%s\n", FILENAME, __FUNCTION__); //FIXME: all deleting stuff is done in Close() + pthread_mutex_lock (&mutex_tag_ist); if (m_stream_tags) gst_tag_list_unref(m_stream_tags); + pthread_mutex_unlock (&mutex_tag_ist); } //Used by Fileplay @@ -471,7 +491,8 @@ void cPlayback::Close(void) // disconnect sync handler callback GstBus * bus = gst_pipeline_get_bus(GST_PIPELINE (m_gst_playbin)); gst_bus_set_sync_handler(bus, NULL, NULL, NULL); - gst_object_unref(bus); + if (bus) + gst_object_unref(bus); lt_info( "%s:%s - GST bus handler closed\n", FILENAME, __FUNCTION__); } @@ -524,8 +545,11 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, mAudioStream = 0; init_jump = -1; - gst_tag_list_unref(m_stream_tags); + pthread_mutex_lock (&mutex_tag_ist); + if (m_stream_tags) + gst_tag_list_unref(m_stream_tags); m_stream_tags = NULL; + pthread_mutex_unlock (&mutex_tag_ist); unlink("/tmp/.id3coverart"); @@ -568,8 +592,7 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, lt_info("%s:%s - filename=%s\n", FILENAME, __FUNCTION__, filename); - guint flags = GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_VIDEO | \ - GST_PLAY_FLAG_TEXT | GST_PLAY_FLAG_NATIVE_VIDEO; + guint flags = GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_NATIVE_VIDEO; /* increase the default 2 second / 2 MB buffer limitations to 5s / 5MB */ int m_buffer_size = 5*1024*1024; @@ -598,7 +621,8 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/, //gstbus handler GstBus * bus = gst_pipeline_get_bus( GST_PIPELINE(m_gst_playbin) ); gst_bus_set_sync_handler(bus, Gst_bus_call, NULL, NULL); - gst_object_unref(bus); + if (bus) + gst_object_unref(bus); first = true; @@ -673,13 +697,19 @@ bool cPlayback::SetAPid(int pid, bool /*ac3*/) { lt_info("%s: pid %i\n", __func__, pid); - int current_audio; + int to_audio = pid; - if(pid != mAudioStream) + for (unsigned int i = 0; i < REC_MAX_APIDS; i++) { + if (real_apids[i]) + if (real_apids[i] == pid) + to_audio = i; + } + + if(to_audio != mAudioStream) { - g_object_set (G_OBJECT (m_gst_playbin), "current-audio", pid, NULL); - printf("%s: switched to audio stream %i\n", __FUNCTION__, pid); - mAudioStream = pid; + g_object_set (G_OBJECT (m_gst_playbin), "current-audio", to_audio, NULL); + printf("%s: switched to audio stream %i\n", __FUNCTION__, to_audio); + mAudioStream = to_audio; } return true; @@ -807,7 +837,9 @@ bool cPlayback::GetPosition(int &position, int &duration) else { if(!gst_element_query_position(m_gst_playbin, fmt, &pts)) + { lt_info( "%s - %d failed\n", __FUNCTION__, __LINE__); + } } position = pts / 1000000.0; // duration @@ -830,21 +862,23 @@ bool cPlayback::SetPosition(int position, bool absolute) { lt_info("%s: pos %d abs %d playing %d\n", __func__, position, absolute, playing); - gint64 time_nanoseconds; - gint64 pos; - GstFormat fmt = GST_FORMAT_TIME; - GstState state; if(m_gst_playbin) { - gst_element_get_state(m_gst_playbin, &state, NULL, GST_CLOCK_TIME_NONE); - - if ( (state == GST_STATE_PAUSED) && first) - { - init_jump = position; - first = false; - return false; + if(first){ + GstState state; + gst_element_get_state(m_gst_playbin, &state, NULL, GST_CLOCK_TIME_NONE); + if ( (state == GST_STATE_PAUSED) && first) + { + init_jump = position; + first = false; + return false; + } } + + gint64 time_nanoseconds; + gint64 pos; + GstFormat fmt = GST_FORMAT_TIME; if (!absolute) { gst_element_query_position(m_gst_playbin, fmt, &pos); @@ -857,7 +891,7 @@ bool cPlayback::SetPosition(int position, bool absolute) time_nanoseconds = position * 1000000.0; } - gst_element_seek(m_gst_playbin, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, time_nanoseconds, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); + gst_element_seek(m_gst_playbin, 1.0, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE), GST_SEEK_TYPE_SET, time_nanoseconds, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); } return true; @@ -880,7 +914,7 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu language->clear(); - for (i = 0; i < n_audio; i++) + for (i = 0; i < n_audio && i < *numpida; i++) { // apids apids[i]= real_apids[i] ? real_apids[i] : i; @@ -889,7 +923,8 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu g_signal_emit_by_name (m_gst_playbin, "get-audio-pad", i, &pad); GstCaps * caps = gst_pad_get_current_caps(pad); - gst_object_unref(pad); + if (pad) + gst_object_unref(pad); if (!caps) continue; @@ -897,12 +932,11 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu GstStructure * structure = gst_caps_get_structure(caps, 0); GstTagList * tags = NULL; gchar * g_lang = NULL; - gchar * g_codec = NULL; // ac3flags if ( gst_structure_has_name (structure, "audio/mpeg")) { - gint mpegversion, layer = -1; + gint mpegversion; if (!gst_structure_get_int (structure, "mpegversion", &mpegversion)) ac3flags[i] = 0; @@ -932,14 +966,15 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu //return atPCM; ac3flags[i] = 0; - gst_caps_unref(caps); + if (caps) + gst_caps_unref(caps); //(ac3flags[i] > 2) ? ac3flags[i] = 1 : ac3flags[i] = 0; g_signal_emit_by_name (m_gst_playbin, "get-audio-tags", i, &tags); - if (tags && GST_IS_TAG_LIST(tags)) + if (tags) { - if (gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang)) + if (GST_IS_TAG_LIST(tags) && gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang)) { std::string slang; if (gst_tag_check_language_code(g_lang)) @@ -1002,22 +1037,40 @@ void cPlayback::GetMetadata(std::vector &keys, std::vector &keys, std::vector