summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmpdemux/demux_lavf.c57
1 files changed, 56 insertions, 1 deletions
diff --git a/libmpdemux/demux_lavf.c b/libmpdemux/demux_lavf.c
index ef4a20ae7f..8457c1d816 100644
--- a/libmpdemux/demux_lavf.c
+++ b/libmpdemux/demux_lavf.c
@@ -75,6 +75,7 @@ typedef struct lavf_priv {
int sstreams[MAX_S_STREAMS];
int cur_program;
int nb_streams_last;
+ bool internet_radio_hack;
}lavf_priv_t;
static int mp_read(void *opaque, uint8_t *buf, int size) {
@@ -608,6 +609,58 @@ static demuxer_t* demux_open_lavf(demuxer_t *demuxer){
return demuxer;
}
+static void check_internet_radio_hack(struct demuxer *demuxer)
+{
+ struct lavf_priv *priv = demuxer->priv;
+ struct AVFormatContext *avfc = priv->avfc;
+
+ if (!matches_avinputformat_name(priv, "ogg"))
+ return;
+ if (priv->nb_streams_last == avfc->nb_streams)
+ return;
+ if (avfc->nb_streams - priv->nb_streams_last == 1
+ && priv->video_streams == 0 && priv->sub_streams == 0
+ && demuxer->a_streams[priv->audio_streams-1]->format == 0x566f // vorbis
+ && (priv->audio_streams == 2 || priv->internet_radio_hack)
+ && demuxer->a_streams[0]->format == 0x566f) {
+ // extradata match could be checked but would require parsing
+ // headers, as the comment section will vary
+ if (!priv->internet_radio_hack) {
+ mp_msg(MSGT_DEMUX, MSGL_V,
+ "[lavf] enabling internet ogg radio hack\n");
+#if LIBAVFORMAT_VERSION_MAJOR < 53
+ mp_tmsg(MSGT_DEMUX, MSGL_WARN, "[lavf] This looks like an "
+ "internet radio ogg stream with track changes.\n"
+ "Playback will likely fail after %d track changes "
+ "due to libavformat limitations.\n"
+ "You may be able to work around that limitation by "
+ "using -demuxer ogg.\n", MAX_STREAMS);
+#endif
+ }
+#if LIBAVFORMAT_VERSION_MAJOR < 53
+ if (avfc->nb_streams == MAX_STREAMS) {
+ mp_tmsg(MSGT_DEMUX, MSGL_WARN, "[lavf] This is the %dth "
+ "track.\nPlayback will likely fail at the next change.\n"
+ "You may be able to work around this limitation by "
+ "using -demuxer ogg.\n", MAX_STREAMS);
+ }
+#endif
+ priv->internet_radio_hack = true;
+ // use new per-track metadata as global metadata
+ AVMetadataTag *t = NULL;
+ AVStream *stream = avfc->streams[avfc->nb_streams - 1];
+ while ((t = av_metadata_get(stream->metadata, "", t,
+ AV_METADATA_IGNORE_SUFFIX)))
+ demux_info_add(demuxer, t->key, t->value);
+ } else {
+ if (priv->internet_radio_hack)
+ mp_tmsg(MSGT_DEMUX, MSGL_WARN, "[lavf] Internet radio ogg hack "
+ "was enabled, but stream characteristics changed.\n"
+ "This may or may not work.\n");
+ priv->internet_radio_hack = false;
+ }
+}
+
static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds){
lavf_priv_t *priv= demux->priv;
AVPacket pkt;
@@ -624,11 +677,13 @@ static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds){
// handle any new streams that might have been added
for (id = priv->nb_streams_last; id < priv->avfc->nb_streams; id++)
handle_stream(demux, priv->avfc, id);
+ check_internet_radio_hack(demux);
+
priv->nb_streams_last = priv->avfc->nb_streams;
id= pkt.stream_index;
- if(id==demux->audio->id){
+ if (id == demux->audio->id || priv->internet_radio_hack) {
// audio
ds=demux->audio;
if(!ds->sh){