update generic gstreamer

Origin commit data
------------------
Branch: master
Commit: 8218368064
Author: TangoCash <eric@loxat.de>
Date: 2017-11-03 (Fri, 03 Nov 2017)


------------------
No further description and justification available within origin commit message!

------------------
This commit was generated by Migit
This commit is contained in:
TangoCash
2017-11-03 21:18:53 +01:00
parent 25dd69fbc9
commit 2d229cf435
3 changed files with 658 additions and 363 deletions

View File

@@ -36,7 +36,9 @@ if ENABLE_GSTREAMER_10
libgeneric_la_SOURCES += \
playback_gst_10.cpp
AM_LDFLAGS += \
-lgstreamer-1.0
-lgstreamer-1.0 \
-lgsttag-1.0 \
-lgstmpegts-1.0
else
libgeneric_la_SOURCES += \
playback.cpp

View File

@@ -26,7 +26,8 @@
#include <config.h>
typedef enum {
typedef enum
{
STATE_STOP,
STATE_PLAY,
STATE_PAUSE,
@@ -35,19 +36,23 @@ typedef enum {
STATE_SLOW
} playstate_t;
typedef enum {
typedef enum
{
PLAYMODE_TS = 0,
PLAYMODE_FILE,
} playmode_t;
struct AVFormatContext;
class cPlayback
{
private:
bool playing;
bool playing, first;
bool decoders_closed;
int mSpeed;
int mAudioStream;
int init_jump;
public:
playstate_t playstate;
@@ -71,6 +76,9 @@ class cPlayback
bool GetSpeed(int &speed) const;
bool GetPosition(int &position, int &duration);
void GetPts(uint64_t &pts);
int GetAPid(void);
int GetVPid(void);
int GetSubtitlePid(void);
bool SetPosition(int position, bool absolute = false);
void FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *numpida, std::string *language);
void FindAllSubtitlePids(int *pids, unsigned int *numpids, std::string *language);
@@ -81,6 +89,11 @@ class cPlayback
uint64_t GetReadCount(void);
void GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
void GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values);
AVFormatContext *GetAVFormatContext();
void ReleaseAVFormatContext();
std::string extra_headers;
std::string user_agent;
//
~cPlayback();
void getMeta();

View File

@@ -46,29 +46,39 @@
static const char * FILENAME = "[playback.cpp]";
#include <gst/gst.h>
#include <gst/tag/tag.h>
#include <gst/mpegts/mpegts.h>
#include <gst/pbutils/missing-plugins.h>
#include <gst/video/videooverlay.h>
typedef enum
{
GST_PLAY_FLAG_VIDEO = 0x00000001,
GST_PLAY_FLAG_AUDIO = 0x00000002,
GST_PLAY_FLAG_TEXT = 0x00000004,
GST_PLAY_FLAG_VIS = 0x00000008,
GST_PLAY_FLAG_SOFT_VOLUME = 0x00000010,
GST_PLAY_FLAG_NATIVE_AUDIO = 0x00000020,
GST_PLAY_FLAG_NATIVE_VIDEO = 0x00000040,
GST_PLAY_FLAG_DOWNLOAD = 0x00000080,
GST_PLAY_FLAG_BUFFERING = 0x000000100
GST_PLAY_FLAG_VIDEO = (1 << 0),
GST_PLAY_FLAG_AUDIO = (1 << 1),
GST_PLAY_FLAG_TEXT = (1 << 2),
GST_PLAY_FLAG_VIS = (1 << 3),
GST_PLAY_FLAG_SOFT_VOLUME = (1 << 4),
GST_PLAY_FLAG_NATIVE_AUDIO = (1 << 5),
GST_PLAY_FLAG_NATIVE_VIDEO = (1 << 6),
GST_PLAY_FLAG_DOWNLOAD = (1 << 7),
GST_PLAY_FLAG_BUFFERING = (1 << 8),
GST_PLAY_FLAG_DEINTERLACE = (1 << 9),
GST_PLAY_FLAG_SOFT_COLORBALANCE = (1 << 10),
GST_PLAY_FLAG_FORCE_FILTERS = (1 << 11),
} GstPlayFlags;
GstElement * m_gst_playbin = NULL;
GstElement * audioSink = NULL;
GstElement * videoSink = NULL;
gchar * uri = NULL;
GstTagList * m_stream_tags = 0;
GstTagList * m_stream_tags = NULL;
static int end_eof = 0;
#define HTTP_TIMEOUT 30
// taken from record.h
#define REC_MAX_APIDS 20
int real_apids[REC_MAX_APIDS];
extern GLFramebuffer *glfb;
@@ -78,6 +88,108 @@ gint match_sinktype(const GValue *velement, const gchar *type)
return strcmp(g_type_name(G_OBJECT_TYPE(element)), type);
}
void resetPids()
{
for (unsigned int i = 0; i < REC_MAX_APIDS; i++) {
real_apids[i] = 0;
}
}
void processMpegTsSection(GstMpegtsSection* section)
{
resetPids();
int cnt = 0;
if (section->section_type == GST_MPEGTS_SECTION_PMT) {
const GstMpegtsPMT* pmt = gst_mpegts_section_get_pmt(section);
for (guint i = 0; i < pmt->streams->len; ++i) {
const GstMpegtsPMTStream* stream = static_cast<const GstMpegtsPMTStream*>(g_ptr_array_index(pmt->streams, i));
if (stream->stream_type == 0x05 || stream->stream_type >= 0x80) {
lt_info_c( "%s:%s Audio Stream pid: %d\n", FILENAME, __FUNCTION__, stream->pid);
real_apids[cnt] = stream->pid;
cnt++;
}
}
}
}
void playbinNotifySource(GObject *object, GParamSpec *unused, gpointer user_data)
{
GstElement *source = NULL;
cPlayback *_this = (cPlayback*)user_data;
g_object_get(object, "source", &source, NULL);
if (source)
{
if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "timeout") != 0)
{
GstElementFactory *factory = gst_element_get_factory(source);
if (factory)
{
const gchar *sourcename = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory));
if (!strcmp(sourcename, "souphttpsrc"))
{
g_object_set(G_OBJECT(source), "timeout", HTTP_TIMEOUT, NULL);
}
}
}
if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "ssl-strict") != 0)
{
g_object_set(G_OBJECT(source), "ssl-strict", FALSE, NULL);
}
if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "user-agent") != 0 && !_this->user_agent.empty())
{
g_object_set(G_OBJECT(source), "user-agent", _this->user_agent.c_str(), NULL);
}
if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "extra-headers") != 0 && !_this->extra_headers.empty())
{
GstStructure *extras = gst_structure_new_empty("extras");
size_t pos = 0;
while (pos != std::string::npos)
{
std::string name, value;
size_t start = pos;
size_t len = std::string::npos;
pos = _this->extra_headers.find('=', pos);
if (pos != std::string::npos)
{
len = pos - start;
pos++;
name = _this->extra_headers.substr(start, len);
start = pos;
len = std::string::npos;
pos = _this->extra_headers.find('&', pos);
if (pos != std::string::npos)
{
len = pos - start;
pos++;
}
value = _this->extra_headers.substr(start, len);
}
if (!name.empty() && !value.empty())
{
GValue header;
lt_info_c( "%s:%s setting extra-header '%s:%s'\n", FILENAME, __FUNCTION__, name.c_str(), value.c_str());
memset(&header, 0, sizeof(GValue));
g_value_init(&header, G_TYPE_STRING);
g_value_set_string(&header, value.c_str());
gst_structure_set_value(extras, name.c_str(), &header);
}
else
{
lt_info_c( "%s:%s Invalid header format %s\n", FILENAME, __FUNCTION__, _this->extra_headers.c_str());
break;
}
}
if (gst_structure_n_fields(extras) > 0)
{
g_object_set(G_OBJECT(source), "extra-headers", extras, NULL);
}
gst_structure_free(extras);
}
gst_object_unref(source);
}
}
GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data)
{
gchar * sourceName;
@@ -148,33 +260,65 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data)
result = gst_tag_list_merge(m_stream_tags, tags, GST_TAG_MERGE_REPLACE);
if (result)
{
if (m_stream_tags && gst_tag_list_is_equal(m_stream_tags, result))
{
gst_tag_list_unref(tags);
gst_tag_list_unref(result);
break;
}
if (m_stream_tags)
gst_tag_list_free(m_stream_tags);
m_stream_tags = result;
gst_tag_list_unref(m_stream_tags);
m_stream_tags = gst_tag_list_copy(result);
gst_tag_list_unref(result);
}
const GValue *gv_image = gst_tag_list_get_value_index(tags, GST_TAG_IMAGE, 0);
if ( gv_image )
{
GstBuffer *buf_image;
buf_image = gst_value_get_buffer (gv_image);
GstSample *sample;
sample = (GstSample *)g_value_get_boxed(gv_image);
buf_image = gst_sample_get_buffer(sample);
int fd = open("/tmp/.id3coverart", O_CREAT|O_WRONLY|O_TRUNC, 0644);
if (fd >= 0)
{
GstMapInfo Info;
gst_buffer_map(buf_image, &Info,(GstMapFlags)( GST_MAP_READ));
int ret = write(fd, Info.data, Info.size);
guint8 *data;
gsize size;
GstMapInfo map;
gst_buffer_map(buf_image, &map, GST_MAP_READ);
data = map.data;
size = map.size;
int ret = write(fd, data, size);
gst_buffer_unmap(buf_image, &map);
close(fd);
gst_buffer_unmap(buf_image, &Info);
lt_info_c( "%s:%s - GST_MESSAGE_INFO: cPlayback::state /tmp/.id3coverart %d bytes written\n", FILENAME, __FUNCTION__ , ret);
lt_info_c("%s:%s - /tmp/.id3coverart %d bytes written\n", FILENAME, __FUNCTION__, ret);
}
//FIXME: how shall playback handle this event???
}
gst_tag_list_free(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;
}
case GST_MESSAGE_ELEMENT:
{
#if 0
if(gst_structure_has_name(gst_message_get_structure(msg), "prepare-window-handle"))
{
// set window id
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC (msg)), glfb->getWindowID());
// reshape window
gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC (msg)), 0, 0, glfb->getOSDWidth(), glfb->getOSDHeight());
// sync frames
gst_video_overlay_expose(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC (msg)));
}
#endif
GstMpegtsSection* section = gst_message_parse_mpegts_section(msg);
if (section) {
processMpegTsSection(section);
gst_mpegts_section_unref(section);
}
}
case GST_MESSAGE_STATE_CHANGED:
{
if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin))
@@ -197,6 +341,8 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data)
case GST_STATE_CHANGE_READY_TO_PAUSED:
{
GstIterator *children;
GValue r = { 0, };
if (audioSink)
{
gst_object_unref(GST_OBJECT(audioSink));
@@ -209,16 +355,27 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data)
videoSink = NULL;
}
children = gst_bin_iterate_recurse(GST_BIN(m_gst_playbin));
GValue r = G_VALUE_INIT;
gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBAudioSink");
if (gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBAudioSink"))
{
audioSink = GST_ELEMENT_CAST(g_value_dup_object (&r));
g_value_unset (&r);
gst_iterator_find_custom(children, (GCompareFunc)match_sinktype, &r, (gpointer)"GstDVBVideoSink");
lt_info_c( "%s %s - audio sink created\n", FILENAME, __FUNCTION__);
}
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"))
{
videoSink = GST_ELEMENT_CAST(g_value_dup_object (&r));
g_value_unset (&r);
lt_info_c( "%s %s - video sink created\n", FILENAME, __FUNCTION__);
}
gst_iterator_free(children);
} break;
}
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
{
} break;
@@ -237,29 +394,14 @@ GstBusSyncReply Gst_bus_call(GstBus * bus, GstMessage *msg, gpointer user_data)
gst_object_unref(GST_OBJECT(videoSink));
videoSink = NULL;
}
} break;
}
break;
case GST_STATE_CHANGE_READY_TO_NULL:
{
} break;
}
break;
}
#if 0
case GST_MESSAGE_ELEMENT:
{
if(gst_structure_has_name(gst_message_get_structure(msg), "prepare-window-handle"))
{
// set window id
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC (msg)), glfb->getWindowID());
// reshape window
gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC (msg)), 0, 0, glfb->getOSDWidth(), glfb->getOSDHeight());
// sync frames
gst_video_overlay_expose(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC (msg)));
}
}
#endif
break;
default:
break;
@@ -295,18 +437,24 @@ cPlayback::cPlayback(int num)
playing = false;
playstate = STATE_STOP;
decoders_closed = false;
first = false;
}
cPlayback::~cPlayback()
{
lt_info( "%s:%s\n", FILENAME, __FUNCTION__);
//FIXME: all deleting stuff is done in Close()
if (m_stream_tags)
gst_tag_list_unref(m_stream_tags);
}
//Used by Fileplay
bool cPlayback::Open(playmode_t PlayMode)
{
lt_info("%s: PlayMode %d\n", __func__, PlayMode);
init_jump = -1;
return true;
}
@@ -327,9 +475,6 @@ void cPlayback::Close(void)
lt_info( "%s:%s - GST bus handler closed\n", FILENAME, __FUNCTION__);
}
if (m_stream_tags)
gst_tag_list_free(m_stream_tags);
// close gst
if (m_gst_playbin)
{
@@ -354,7 +499,9 @@ void cPlayback::Close(void)
lt_info( "%s:%s - GST playbin closed\n", FILENAME, __FUNCTION__);
m_gst_playbin = NULL;
}
}
// start
@@ -367,16 +514,32 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/,
{
lt_info( "%s:%s\n", FILENAME, __FUNCTION__);
if (!headers.empty())
extra_headers = headers;
else
extra_headers.clear();
resetPids();
mAudioStream = 0;
init_jump = -1;
gst_tag_list_unref(m_stream_tags);
m_stream_tags = NULL;
unlink("/tmp/.id3coverart");
//create playback path
char file[400] = {""};
bool isHTTP = false;
if(!strncmp("http://", filename, 7))
{
isHTTP = true;
}
else if(!strncmp("https://", filename, 8))
{
isHTTP = true;
}
else if(!strncmp("file://", filename, 7))
{
isHTTP = false;
@@ -397,18 +560,20 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/,
{
isHTTP = true;
}
else
strcat(file, "file://");
strcat(file, filename);
if (isHTTP)
uri = g_uri_escape_string(filename, G_URI_RESERVED_CHARS_GENERIC_DELIMITERS, true);
uri = g_strdup_printf ("%s", filename);
else
uri = g_filename_to_uri(filename, NULL, NULL);
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;
/* increase the default 2 second / 2 MB buffer limitations to 5s / 5MB */
int m_buffer_size = 5*1024*1024;
// create gst pipeline
m_gst_playbin = gst_element_factory_make ("playbin", "playbin");
@@ -416,26 +581,40 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/,
{
lt_info("%s:%s - m_gst_playbin\n", FILENAME, __FUNCTION__);
guint flags;
g_object_get(G_OBJECT (m_gst_playbin), "flags", &flags, NULL);
/* avoid video conversion, let the (hardware) sinks handle that */
flags |= GST_PLAY_FLAG_NATIVE_VIDEO;
/* volume control is done by hardware */
flags &= ~GST_PLAY_FLAG_SOFT_VOLUME;
if(isHTTP)
{
g_signal_connect (G_OBJECT (m_gst_playbin), "notify::source", G_CALLBACK (playbinNotifySource), this);
// set buffer size
g_object_set(G_OBJECT(m_gst_playbin), "buffer-size", m_buffer_size, NULL);
g_object_set(G_OBJECT(m_gst_playbin), "buffer-duration", 5LL * GST_SECOND, NULL);
flags |= GST_PLAY_FLAG_BUFFERING;
}
g_object_set(G_OBJECT (m_gst_playbin), "flags", flags, NULL);
g_object_set(G_OBJECT (m_gst_playbin), "uri", uri, NULL);
g_object_set(G_OBJECT (m_gst_playbin), "flags", flags, NULL);
//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);
first = true;
// state playing
gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING);
if(isHTTP)
{
gst_element_set_state(GST_ELEMENT(m_gst_playbin), GST_STATE_PLAYING);
playstate = STATE_PLAY;
}
else
{
gst_element_set_state(GST_ELEMENT(m_gst_playbin), GST_STATE_PAUSED);
playstate = STATE_PAUSE;
}
playing = true;
playstate = STATE_PLAY;
}
else
{
@@ -447,12 +626,6 @@ bool cPlayback::Start(char *filename, int /*vpid*/, int /*vtype*/, int /*apid*/,
g_free(uri);
// set buffer size
/* increase the default 2 second / 2 MB buffer limitations to 5s / 5MB */
int m_buffer_size = 5*1024*1024;
//g_object_set(G_OBJECT(m_gst_playbin), "buffer-duration", 5LL * GST_SECOND, NULL);
g_object_set(G_OBJECT(m_gst_playbin), "buffer-size", m_buffer_size, NULL);
return true;
}
@@ -514,25 +687,17 @@ bool cPlayback::SetAPid(int pid , bool /*ac3*/)
void cPlayback::trickSeek(int ratio)
{
bool validposition = false;
GstFormat fmt = GST_FORMAT_TIME;
gint64 pos = 0;
int position;
int duration;
if( GetPosition(position, duration) )
{
validposition = true;
pos = position;
}
gst_element_set_state(m_gst_playbin, GST_STATE_PLAYING);
if (validposition)
if (gst_element_query_position(m_gst_playbin, fmt, &pos))
{
if(ratio >= 0.0)
gst_element_seek(m_gst_playbin, ratio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, -1);
gst_element_seek(m_gst_playbin, ratio, fmt, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, -1);
else
gst_element_seek(m_gst_playbin, ratio, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, pos);
gst_element_seek(m_gst_playbin, ratio, fmt, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, pos);
}
}
@@ -574,6 +739,12 @@ bool cPlayback::SetSpeed(int speed)
//
playstate = STATE_REW;
}
if (init_jump > -1)
{
SetPosition(init_jump,true);
init_jump = -1;
}
}
mSpeed = speed;
@@ -624,13 +795,21 @@ bool cPlayback::GetPosition(int &position, int &duration)
{
//position
GstFormat fmt = GST_FORMAT_TIME; //Returns time in nanosecs
gint64 pts = 0;
unsigned long long int sec = 0;
gst_element_query_position(m_gst_playbin, fmt, &pts);
if (audioSink || videoSink)
{
g_signal_emit_by_name(audioSink ? audioSink : videoSink, "get-decoder-time", &pts);
if (!GST_CLOCK_TIME_IS_VALID(pts))
{
lt_info( "%s - %d failed\n", __FUNCTION__, __LINE__);
}
}
else
{
if(!gst_element_query_position(m_gst_playbin, fmt, &pts))
lt_info( "%s - %d failed\n", __FUNCTION__, __LINE__);
}
position = pts / 1000000.0;
// duration
GstFormat fmt_d = GST_FORMAT_TIME; //Returns time in nanosecs
double length = 0;
@@ -651,19 +830,32 @@ bool cPlayback::SetPosition(int position, bool absolute)
{
lt_info("%s: pos %d abs %d playing %d\n", __func__, position, absolute, playing);
if(playing == false)
return false;
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 (!absolute)
{
gst_element_query_position(m_gst_playbin, fmt, &pos);
time_nanoseconds = pos + (position * 1000000.0);
if(time_nanoseconds < 0)
time_nanoseconds = 0;
}
else
{
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);
}
@@ -678,32 +870,34 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu
if(m_gst_playbin)
{
gint i, n_audio = 0;
//GstStructure * structure = NULL;
// get audio
g_object_get (m_gst_playbin, "n-audio", &n_audio, NULL);
printf("%s: %d audio\n", __FUNCTION__, n_audio);
lt_info("%s: %d audio\n", __FUNCTION__, n_audio);
if(n_audio == 0)
return;
language->clear();
for (i = 0; i < n_audio; i++)
{
// apids
apids[i]=i;
apids[i]= real_apids[i] ? real_apids[i] : i;
GstPad * pad = 0;
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 (!caps)
continue;
GstStructure * structure = gst_caps_get_structure(caps, 0);
//const gchar *g_type = gst_structure_get_name(structure);
//if (!structure)
//return atUnknown;
//ac3flags[0] = 0;
GstTagList * tags = NULL;
gchar * g_lang = NULL;
gchar * g_codec = NULL;
// ac3flags
if ( gst_structure_has_name (structure, "audio/mpeg"))
@@ -711,23 +905,11 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu
gint mpegversion, layer = -1;
if (!gst_structure_get_int (structure, "mpegversion", &mpegversion))
//return atUnknown;
ac3flags[i] = 0;
switch (mpegversion)
{
case 1:
/*
{
gst_structure_get_int (structure, "layer", &layer);
if ( layer == 3 )
return atMP3;
else
return atMPEG;
ac3flags[0] = 4;
break;
}
*/
ac3flags[i] = 4;
case 2:
//return atAAC;
@@ -751,9 +933,21 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu
ac3flags[i] = 0;
gst_caps_unref(caps);
}
// numpids
//(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 (gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang))
{
language[i] = std::string(gst_tag_get_language_name(g_lang)).c_str();
lt_info("%s: language:%s\n", __FUNCTION__, language[i].c_str());
g_free(g_lang);
}
gst_tag_list_free(tags);
}
}
*numpida=i;
}
}
@@ -800,6 +994,62 @@ void cPlayback::GetMetadata(std::vector<std::string> &keys, std::vector<std::str
{
keys.clear();
values.clear();
if (gst_tag_list_is_empty (m_stream_tags))
return;
for (guint i = 0, icnt = gst_tag_list_n_tags(m_stream_tags); i < icnt; i++)
{
const gchar *name = gst_tag_list_nth_tag_name(m_stream_tags, i);
if (!name)
{
continue;
}
for (guint j = 0, jcnt = gst_tag_list_get_tag_size(m_stream_tags, name); j < jcnt; j++)
{
const GValue *val;
val = gst_tag_list_get_value_index(m_stream_tags, name, j);
if (G_VALUE_HOLDS_STRING(val))
{
keys.push_back(name);
values.push_back(g_value_get_string(val));
}
else if (G_VALUE_HOLDS_UINT(val))
{
char buffer [50];
keys.push_back(name);
sprintf (buffer, "%u", g_value_get_uint(val));
values.push_back(buffer);
}
else if (G_VALUE_HOLDS_DOUBLE(val))
{
char buffer [50];
keys.push_back(name);
sprintf (buffer, "%f", g_value_get_double(val));
values.push_back(buffer);
}
else if (G_VALUE_HOLDS_BOOLEAN(val))
{
keys.push_back(name);
values.push_back(g_value_get_boolean(val) ? "true" : "false");
}
else if (GST_VALUE_HOLDS_DATE_TIME(val))
{
GstDateTime *dt = (GstDateTime *) g_value_get_boxed(val);
keys.push_back(name);
values.push_back(gst_date_time_to_iso8601_string(dt));
}
else if (G_VALUE_HOLDS(val, G_TYPE_DATE))
{
keys.push_back(name);
values.push_back(gst_value_serialize(val));
}
}
}
printf("%s:%s %d tags found\n", FILENAME, __func__, (int)keys.size());
}
void cPlayback::FindAllTeletextsubtitlePids(int *, unsigned int *numpids, std::string *, int *, int *)
@@ -830,3 +1080,33 @@ uint64_t cPlayback::GetReadCount()
{
return 0;
}
int cPlayback::GetAPid(void)
{
gint current_audio = 0;
g_object_get (m_gst_playbin, "current-audio", &current_audio, NULL);
lt_info("%s: %d audio\n", __FUNCTION__, current_audio);
return current_audio;
}
int cPlayback::GetVPid(void)
{
gint current_video = 0;
g_object_get (m_gst_playbin, "current-video", &current_video, NULL);
lt_info("%s: %d video\n", __FUNCTION__, current_video);
return current_video;
}
int cPlayback::GetSubtitlePid(void)
{
return 0;
}
AVFormatContext *cPlayback::GetAVFormatContext()
{
return NULL;
}
void cPlayback::ReleaseAVFormatContext()
{
}