summaryrefslogtreecommitdiffstats
path: root/libmpdemux
diff options
context:
space:
mode:
authorUoti Urpala <uau@glyph.nonexistent.invalid>2010-04-26 18:46:18 +0300
committerUoti Urpala <uau@glyph.nonexistent.invalid>2010-04-26 18:46:18 +0300
commit9a34ae4fd05226feb5b82573a4283c3cd8586b8a (patch)
tree157e9ea076c46fe37e626704a7b81c6e8b2a6db3 /libmpdemux
parent8df340271e868252e7398307e126ea12083d426b (diff)
parent91a84df7d0b19ca510a78191233f17c2d7691b95 (diff)
downloadmpv-9a34ae4fd05226feb5b82573a4283c3cd8586b8a.tar.bz2
mpv-9a34ae4fd05226feb5b82573a4283c3cd8586b8a.tar.xz
Merge svn changes up to r31050
Diffstat (limited to 'libmpdemux')
-rw-r--r--libmpdemux/demux_ogg.c2797
1 files changed, 1437 insertions, 1360 deletions
diff --git a/libmpdemux/demux_ogg.c b/libmpdemux/demux_ogg.c
index acb783d71f..e872ad5156 100644
--- a/libmpdemux/demux_ogg.c
+++ b/libmpdemux/demux_ogg.c
@@ -60,112 +60,108 @@ int _ilog (unsigned int); /* defined in many places in theora/lib/ */
*/
#ifdef CONFIG_OGGTHEORA
typedef struct theora_struct_st {
- theora_state st;
+ theora_state st;
theora_comment cc;
- theora_info inf;
+ theora_info inf;
} theora_struct_t;
#endif
//// OggDS headers
// Header for the new header format
-typedef struct stream_header_video
-{
- ogg_int32_t width;
- ogg_int32_t height;
+typedef struct stream_header_video {
+ ogg_int32_t width;
+ ogg_int32_t height;
} stream_header_video;
-typedef struct stream_header_audio
-{
- ogg_int16_t channels;
- ogg_int16_t blockalign;
- ogg_int32_t avgbytespersec;
+typedef struct stream_header_audio {
+ ogg_int16_t channels;
+ ogg_int16_t blockalign;
+ ogg_int32_t avgbytespersec;
} stream_header_audio;
-typedef struct __attribute__((__packed__)) stream_header
-{
- char streamtype[8];
- char subtype[4];
+typedef struct __attribute__((__packed__)) stream_header {
+ char streamtype[8];
+ char subtype[4];
- ogg_int32_t size; // size of the structure
+ ogg_int32_t size; // size of the structure
- ogg_int64_t time_unit; // in reference time
- ogg_int64_t samples_per_unit;
- ogg_int32_t default_len; // in media time
+ ogg_int64_t time_unit; // in reference time
+ ogg_int64_t samples_per_unit;
+ ogg_int32_t default_len; // in media time
- ogg_int32_t buffersize;
- ogg_int16_t bits_per_sample;
+ ogg_int32_t buffersize;
+ ogg_int16_t bits_per_sample;
- ogg_int16_t padding;
+ ogg_int16_t padding;
- union
- {
- // Video specific
- stream_header_video video;
- // Audio specific
- stream_header_audio audio;
- } sh;
+ union {
+ // Video specific
+ stream_header_video video;
+ // Audio specific
+ stream_header_audio audio;
+ } sh;
} stream_header;
/// Our private datas
typedef struct ogg_syncpoint {
- int64_t granulepos;
- off_t page_pos;
+ int64_t granulepos;
+ off_t page_pos;
} ogg_syncpoint_t;
/// A logical stream
typedef struct ogg_stream {
- /// Timestamping stuff
- float samplerate; /// granulpos 2 time
- int64_t lastpos;
- int32_t lastsize;
- int keyframe_frequency_force;
-
- // Logical stream state
- ogg_stream_state stream;
- int hdr_packets;
- int vorbis;
- int speex;
- int theora;
- int flac;
- int text;
- int id;
-
- vorbis_info vi;
- int vi_initialized;
-
- void *ogg_d;
+ /// Timestamping stuff
+ float samplerate; /// granulpos 2 time
+ int64_t lastpos;
+ int32_t lastsize;
+ int keyframe_frequency_force;
+
+ // Logical stream state
+ ogg_stream_state stream;
+ int hdr_packets;
+ int vorbis;
+ int speex;
+ int theora;
+ int flac;
+ int text;
+ int id;
+
+ vorbis_info vi;
+ int vi_initialized;
+
+ void *ogg_d;
} ogg_stream_t;
typedef struct ogg_demuxer {
- /// Physical stream state
- ogg_sync_state sync;
- /// Current page
- ogg_page page;
- /// Logical streams
- ogg_stream_t *subs;
- int num_sub;
- ogg_syncpoint_t* syncpoints;
- int num_syncpoint;
- off_t pos, last_size;
- int64_t initial_granulepos;
- int64_t final_granulepos;
- int64_t duration;
-
- /* Used for subtitle switching. */
- int n_text;
- int *text_ids;
- char **text_langs;
+ /// Physical stream state
+ ogg_sync_state sync;
+ /// Current page
+ ogg_page page;
+ /// Logical streams
+ ogg_stream_t *subs;
+ int num_sub;
+ ogg_syncpoint_t *syncpoints;
+ int num_syncpoint;
+ off_t pos, last_size;
+ int64_t initial_granulepos;
+ int64_t final_granulepos;
+ int64_t duration;
+
+ /* Used for subtitle switching. */
+ int n_text;
+ int *text_ids;
+ char **text_langs;
} ogg_demuxer_t;
#define NUM_VORBIS_HDR_PACKETS 3
/// Some defines from OggDS
-#define PACKET_TYPE_HEADER 0x01
-#define PACKET_TYPE_BITS 0x07
-#define PACKET_LEN_BITS01 0xc0
-#define PACKET_LEN_BITS2 0x02
-#define PACKET_IS_SYNCPOINT 0x08
+#define PACKET_TYPE_HEADER 0x01
+#define PACKET_TYPE_BITS 0x07
+#define PACKET_LEN_BITS01 0xc0
+#define PACKET_LEN_BITS2 0x02
+#define PACKET_IS_SYNCPOINT 0x08
extern char *dvdsub_lang, *audio_lang;
@@ -181,192 +177,192 @@ static subtitle ogg_sub;
static void demux_ogg_add_sub(ogg_stream_t *os, ogg_packet *pack)
{
- int lcv;
- char *packet = pack->packet;
-
- if (pack->bytes < 4)
- return;
- mp_msg(MSGT_DEMUX,MSGL_DBG2,"\ndemux_ogg_add_sub %02X %02X %02X '%s'\n",
- (unsigned char)packet[0],
- (unsigned char)packet[1],
- (unsigned char)packet[2],
- &packet[3]);
-
- if (((unsigned char)packet[0]) == 0x88) { // some subtitle text
- // Find data start
- double endpts = MP_NOPTS_VALUE;
- int32_t duration = 0;
- int16_t hdrlen = (*packet & PACKET_LEN_BITS01)>>6, i;
- hdrlen |= (*packet & PACKET_LEN_BITS2) <<1;
- lcv = 1 + hdrlen;
- if (pack->bytes < lcv)
- return;
- for (i = hdrlen; i > 0; i--) {
- duration <<= 8;
- duration |= (unsigned char)packet[i];
- }
- if (hdrlen > 0 && duration > 0) {
- float pts;
- if(pack->granulepos == -1)
- pack->granulepos = os->lastpos + os->lastsize;
- pts = (float)pack->granulepos/(float)os->samplerate;
- endpts = 1.0 + pts + (float)duration/1000.0;
+ int lcv;
+ char *packet = pack->packet;
+
+ if (pack->bytes < 4)
+ return;
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "\ndemux_ogg_add_sub %02X %02X %02X '%s'\n",
+ (unsigned char)packet[0],
+ (unsigned char)packet[1],
+ (unsigned char)packet[2],
+ &packet[3]);
+
+ if (((unsigned char)packet[0]) == 0x88) { // some subtitle text
+ // Find data start
+ double endpts = MP_NOPTS_VALUE;
+ int32_t duration = 0;
+ int16_t hdrlen = (*packet & PACKET_LEN_BITS01) >> 6, i;
+
+ hdrlen |= (*packet & PACKET_LEN_BITS2) << 1;
+ lcv = 1 + hdrlen;
+ if (pack->bytes < lcv)
+ return;
+ for (i = hdrlen; i > 0; i--) {
+ duration <<= 8;
+ duration |= (unsigned char)packet[i];
+ }
+ if (hdrlen > 0 && duration > 0) {
+ float pts;
+
+ if (pack->granulepos == -1)
+ pack->granulepos = os->lastpos + os->lastsize;
+ pts = (float)pack->granulepos / (float)os->samplerate;
+ endpts = 1.0 + pts + (float)duration / 1000.0;
+ }
+ sub_clear_text(&ogg_sub, MP_NOPTS_VALUE);
+ sub_add_text(&ogg_sub, &packet[lcv], pack->bytes - lcv, endpts);
}
- sub_clear_text(&ogg_sub, MP_NOPTS_VALUE);
- sub_add_text(&ogg_sub, &packet[lcv], pack->bytes - lcv, endpts);
- }
- mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg sub lines: %d first: '%s'\n",
- ogg_sub.lines, ogg_sub.text[0]);
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg sub lines: %d first: '%s'\n",
+ ogg_sub.lines, ogg_sub.text[0]);
#ifdef CONFIG_ICONV
- subcp_recode(&ogg_sub);
+ subcp_recode(&ogg_sub);
#endif
- vo_sub = &ogg_sub;
- vo_osd_changed(OSDTYPE_SUBTITLE);
+ vo_sub = &ogg_sub;
+ vo_osd_changed(OSDTYPE_SUBTITLE);
}
// get the logical stream of the current page
// fill os if non NULL and return the stream id
-static int demux_ogg_get_page_stream(ogg_demuxer_t* ogg_d,ogg_stream_state** os) {
- int id,s_no;
- ogg_page* page = &ogg_d->page;
-
- s_no = ogg_page_serialno(page);
-
- for(id= 0; id < ogg_d->num_sub ; id++) {
- if(s_no == ogg_d->subs[id].stream.serialno)
- break;
- }
-
- if(id == ogg_d->num_sub) {
- // If we have only one vorbis stream allow the stream id to change
- // it's normal on radio stream (each song have an different id).
- // But we (or the codec?) should check that the samplerate, etc
- // doesn't change (for radio stream it's ok)
- if(ogg_d->num_sub == 1 && ogg_d->subs[0].vorbis) {
- ogg_stream_reset(&ogg_d->subs[0].stream);
- ogg_stream_init(&ogg_d->subs[0].stream,s_no);
- id = 0;
- } else
- return -1;
- }
+static int demux_ogg_get_page_stream(ogg_demuxer_t *ogg_d,
+ ogg_stream_state **os)
+{
+ int id, s_no;
+ ogg_page *page = &ogg_d->page;
- if(os)
- *os = &ogg_d->subs[id].stream;
+ s_no = ogg_page_serialno(page);
- return id;
+ for (id = 0; id < ogg_d->num_sub; id++)
+ if (s_no == ogg_d->subs[id].stream.serialno)
+ break;
-}
+ if (id == ogg_d->num_sub) {
+ // If we have only one vorbis stream allow the stream id to change
+ // it's normal on radio stream (each song have an different id).
+ // But we (or the codec?) should check that the samplerate, etc
+ // doesn't change (for radio stream it's ok)
+ if (ogg_d->num_sub == 1 && ogg_d->subs[0].vorbis) {
+ ogg_stream_reset(&ogg_d->subs[0].stream);
+ ogg_stream_init(&ogg_d->subs[0].stream, s_no);
+ id = 0;
+ } else
+ return -1;
+ }
-static unsigned char* demux_ogg_read_packet(ogg_stream_t* os,ogg_packet* pack,float* pts,int* flags, int samplesize) {
- unsigned char* data = pack->packet;
- int size = pack->bytes;
+ if (os)
+ *os = &ogg_d->subs[id].stream;
- *pts = MP_NOPTS_VALUE;
- *flags = 0;
+ return id;
+}
- if(os->vorbis) {
- if(*pack->packet & PACKET_TYPE_HEADER)
- os->hdr_packets++;
- else
- {
- vorbis_info *vi;
- int32_t blocksize = 0;
-
- // When we dump the audio, there is no vi, but we don't care of timestamp in this case
- vi = os->vi_initialized ? &os->vi : NULL;
- if (vi)
- blocksize = vorbis_packet_blocksize(vi,pack) / samplesize;
- // Calculate the timestamp if the packet don't have any
- if(pack->granulepos == -1) {
- pack->granulepos = os->lastpos;
- if(os->lastsize > 0)
- pack->granulepos += os->lastsize;
- } else
- *flags = 1;
- if (vi)
- *pts = pack->granulepos / (float)vi->rate;
- os->lastsize = blocksize;
- os->lastpos = pack->granulepos;
- }
- } else if (os->speex) {
- // whole packet (default)
+static unsigned char *demux_ogg_read_packet(ogg_stream_t *os, ogg_packet *pack,
+ float *pts, int *flags,
+ int samplesize)
+{
+ unsigned char *data = pack->packet;
+ int size = pack->bytes;
+
+ *pts = MP_NOPTS_VALUE;
+ *flags = 0;
+
+ if (os->vorbis) {
+ if (*pack->packet & PACKET_TYPE_HEADER) {
+ os->hdr_packets++;
+ } else {
+ vorbis_info *vi;
+ int32_t blocksize = 0;
+
+ // When we dump the audio, there is no vi, but we don't care of timestamp in this case
+ vi = os->vi_initialized ? &os->vi : NULL;
+ if (vi)
+ blocksize = vorbis_packet_blocksize(vi, pack) / samplesize;
+ // Calculate the timestamp if the packet don't have any
+ if (pack->granulepos == -1) {
+ pack->granulepos = os->lastpos;
+ if (os->lastsize > 0)
+ pack->granulepos += os->lastsize;
+ } else
+ *flags = 1;
+ if (vi)
+ *pts = pack->granulepos / (float)vi->rate;
+ os->lastsize = blocksize;
+ os->lastpos = pack->granulepos;
+ }
+ } else if (os->speex) {
+ // whole packet (default)
# ifdef CONFIG_OGGTHEORA
- } else if (os->theora) {
- /* we pass complete packets to theora, mustn't strip the header! */
- os->lastsize = 1;
-
- /* header packets begin on 1-bit: thus check (*data&0x80). We don't
- have theora_state st, until all header packets were passed to the
- decoder. */
- if (!size || !(*data&0x80))
- {
- int keyframe_granule_shift=_ilog(os->keyframe_frequency_force-1);
- int64_t iframemask = (1 << keyframe_granule_shift) - 1;
-
- if (pack->granulepos >= 0)
- {
- os->lastpos = pack->granulepos >> keyframe_granule_shift;
- os->lastpos += pack->granulepos & iframemask;
- *flags = (pack->granulepos & iframemask) == 0;
- }
- else
- {
- os->lastpos++;
- }
- pack->granulepos = os->lastpos;
- *pts = (double)os->lastpos / (double)os->samplerate;
- }
+ } else if (os->theora) {
+ /* we pass complete packets to theora, mustn't strip the header! */
+ os->lastsize = 1;
+
+ /* header packets begin on 1-bit: thus check (*data&0x80). We don't
+ have theora_state st, until all header packets were passed to the
+ decoder. */
+ if (!size || !(*data&0x80)) {
+ int keyframe_granule_shift = _ilog(os->keyframe_frequency_force - 1);
+ int64_t iframemask = (1 << keyframe_granule_shift) - 1;
+
+ if (pack->granulepos >= 0) {
+ os->lastpos = pack->granulepos >> keyframe_granule_shift;
+ os->lastpos += pack->granulepos & iframemask;
+ *flags = (pack->granulepos & iframemask) == 0;
+ } else {
+ os->lastpos++;
+ }
+ pack->granulepos = os->lastpos;
+ *pts = (double)os->lastpos / (double)os->samplerate;
+ }
#endif /* CONFIG_OGGTHEORA */
- } else if (os->flac) {
- /* we pass complete packets to flac, mustn't strip the header! */
- if (os->flac == 2 && pack->packet[0] != 0xff)
- return NULL;
- } else {
- if(*pack->packet & PACKET_TYPE_HEADER)
- os->hdr_packets++;
- else {
- // Find data start
- int16_t hdrlen = (*pack->packet & PACKET_LEN_BITS01)>>6;
- hdrlen |= (*pack->packet & PACKET_LEN_BITS2) <<1;
- data = pack->packet + 1 + hdrlen;
- // Calculate the timestamp
- if(pack->granulepos == -1)
- pack->granulepos = os->lastpos + (os->lastsize ? os->lastsize : 1);
- // If we already have a timestamp it can be a syncpoint
- if(*pack->packet & PACKET_IS_SYNCPOINT)
- *flags = 1;
- *pts = pack->granulepos/os->samplerate;
- // Save the packet length and timestamp
- os->lastsize = 0;
- while(hdrlen) {
- os->lastsize <<= 8;
- os->lastsize |= pack->packet[hdrlen];
- hdrlen--;
+ } else if (os->flac) {
+ /* we pass complete packets to flac, mustn't strip the header! */
+ if (os->flac == 2 && pack->packet[0] != 0xff)
+ return NULL;
+ } else {
+ if (*pack->packet & PACKET_TYPE_HEADER) {
+ os->hdr_packets++;
+ } else {
+ // Find data start
+ int16_t hdrlen = (*pack->packet & PACKET_LEN_BITS01) >> 6;
+
+ hdrlen |= (*pack->packet & PACKET_LEN_BITS2) << 1;
+ data = pack->packet + 1 + hdrlen;
+ // Calculate the timestamp
+ if (pack->granulepos == -1)
+ pack->granulepos = os->lastpos + (os->lastsize ? os->lastsize : 1);
+ // If we already have a timestamp it can be a syncpoint
+ if (*pack->packet & PACKET_IS_SYNCPOINT)
+ *flags = 1;
+ *pts = pack->granulepos / os->samplerate;
+ // Save the packet length and timestamp
+ os->lastsize = 0;
+ while (hdrlen) {
+ os->lastsize <<= 8;
+ os->lastsize |= pack->packet[hdrlen];
+ hdrlen--;
+ }
+ os->lastpos = pack->granulepos;
+ }
}
- os->lastpos = pack->granulepos;
- }
- }
- return data;
+ return data;
}
// check if clang has substring from comma separated langlist
static int demux_ogg_check_lang(const char *clang, const char *langlist)
{
- const char *c;
-
- if (!langlist || !*langlist)
+ const char *c;
+
+ if (!langlist || !*langlist)
+ return 0;
+ while ((c = strchr(langlist, ','))) {
+ if (!strncasecmp(clang, langlist, c - langlist))
+ return 1;
+ langlist = &c[1];
+ }
+ if (!strncasecmp(clang, langlist, strlen(langlist)))
+ return 1;
return 0;
- while ((c = strchr(langlist, ',')))
- {
- if (!strncasecmp(clang, langlist, c - langlist))
- return 1;
- langlist = &c[1];
- }
- if (!strncasecmp(clang, langlist, strlen(langlist)))
- return 1;
- return 0;
}
/** \brief Change the current subtitle stream and return its ID.
@@ -377,1216 +373,1297 @@ static int demux_ogg_check_lang(const char *clang, const char *langlist)
\returns The Ogg stream number ( = page serial number) of the newly selected
track.
-*/
+ */
static int demux_ogg_sub_id(demuxer_t *demuxer, int index)
{
- ogg_demuxer_t *ogg_d = demuxer->priv;
- return (index < 0) ? index : (index >= ogg_d->n_text) ? -1 : ogg_d->text_ids[index];
+ ogg_demuxer_t *ogg_d = demuxer->priv;
+ return (index < 0) ? index : (index >= ogg_d->n_text) ? -1 : ogg_d->text_ids[index];
}
/** \brief Translate the ogg track number into the subtitle number.
* \param demuxer The demuxer about whose subtitles we are inquiring.
* \param id The ogg track number of the subtitle track.
*/
-static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id) {
- ogg_demuxer_t *ogg_d = demuxer->priv;
- int i;
- for (i = 0; i < ogg_d->n_text; i++)
- if (ogg_d->text_ids[i] == id) return i;
- return -1;
+static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id)
+{
+ ogg_demuxer_t *ogg_d = demuxer->priv;
+ int i;
+
+ for (i = 0; i < ogg_d->n_text; i++)
+ if (ogg_d->text_ids[i] == id)
+ return i;
+ return -1;
}
/// Try to print out comments and also check for LANGUAGE= tag
-static void demux_ogg_check_comments(demuxer_t *d, ogg_stream_t *os, int id, vorbis_comment *vc)
+static void demux_ogg_check_comments(demuxer_t *d, ogg_stream_t *os,
+ int id, vorbis_comment *vc)
{
- const char *hdr, *val;
- char **cmt = vc->user_comments;
- int index, i;
- ogg_demuxer_t *ogg_d = d->priv;
- static const struct table {
- const char *ogg;
- const char *mp;
- } table[] = {
- { "ENCODED_USING", "Software" },
- { "ENCODER_URL", "Encoder URL" },
- { "TITLE", "Title" },
- { "ARTIST", "Artist" },
- { "COMMENT", "Comments" },
- { "DATE", "Creation Date" },
- { "GENRE", "Genre" },
- { "ALBUM", "Album" },
- { "TRACKNUMBER", "Track" },
- { NULL, NULL },
- };
-
- while(*cmt)
- {
- hdr = NULL;
- if (!strncasecmp(*cmt, "LANGUAGE=", 9))
- {
- val = *cmt + 9;
- if (ogg_d->subs[id].text)
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", ogg_d->subs[id].id, val);
- else if (id != d->video->id)
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n", ogg_d->subs[id].id, val);
- if (ogg_d->subs[id].text)
- mp_msg(MSGT_DEMUX, MSGL_INFO, "[Ogg] Language for -sid %d is '-slang \"%s\"'\n", ogg_d->subs[id].id, val);
- // copy this language name into the array
- index = demux_ogg_sub_reverse_id(d, id);
- if (index >= 0) {
- sh_sub_t* sh;
- // in case of malicious files with more than one lang per track:
- if (ogg_d->text_langs[index]) free(ogg_d->text_langs[index]);
- ogg_d->text_langs[index] = strdup(val);
- sh = d->s_streams[index];
- if (sh && sh->lang) free(sh->lang);
- if (sh) sh->lang = strdup(val);
- }
- // check for -slang if subs are uninitialized yet
- if (os->text && d->sub->id < 0 && demux_ogg_check_lang(val, dvdsub_lang))
- {
- d->sub->id = index;
- d->opts->sub_id = index;
- mp_msg(MSGT_DEMUX, MSGL_V, "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n", id, val);
- }
- else
- hdr = "Language";
- }
- else {
- for (i = 0; table[i].ogg; i++)
- {
- if (!strncasecmp(*cmt, table[i].ogg, strlen(table[i].ogg)) &&
- (*cmt)[strlen(table[i].ogg)] == '=')
- {
- hdr = table[i].mp;
- val = *cmt + strlen(table[i].ogg) + 1;
- }
- }
+ const char *hdr, *val;
+ char **cmt = vc->user_comments;
+ int index, i;
+ ogg_demuxer_t *ogg_d = d->priv;
+ static const struct table {
+ const char *ogg;
+ const char *mp;
+ } table[] = {
+ { "ENCODED_USING", "Software" },
+ { "ENCODER_URL", "Encoder URL" },
+ { "TITLE", "Title" },
+ { "ARTIST", "Artist" },
+ { "COMMENT", "Comments" },
+ { "DATE", "Creation Date" },
+ { "GENRE", "Genre" },
+ { "ALBUM", "Album" },
+ { "TRACKNUMBER", "Track" },
+ { NULL, NULL },
+ };
+
+ while (*cmt) {
+ hdr = NULL;
+ if (!strncasecmp(*cmt, "LANGUAGE=", 9)) {
+ val = *cmt + 9;
+ if (ogg_d->subs[id].text)
+ mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n",
+ ogg_d->subs[id].id, val);
+ else if (id != d->video->id)
+ mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n",
+ ogg_d->subs[id].id, val);
+ if (ogg_d->subs[id].text)
+ mp_msg(MSGT_DEMUX, MSGL_INFO,
+ "[Ogg] Language for -sid %d is '-slang \"%s\"'\n",
+ ogg_d->subs[id].id, val);
+ // copy this language name into the array
+ index = demux_ogg_sub_reverse_id(d, id);
+ if (index >= 0) {
+ sh_sub_t *sh;
+
+ // in case of malicious files with more than one lang per track:
+ if (ogg_d->text_langs[index])
+ free(ogg_d->text_langs[index]);
+ ogg_d->text_langs[index] = strdup(val);
+ sh = d->s_streams[index];
+ if (sh && sh->lang)
+ free(sh->lang);
+ if (sh)
+ sh->lang = strdup(val);
+ }
+ // check for -slang if subs are uninitialized yet
+ if (os->text && d->sub->id < 0 && demux_ogg_check_lang(val, dvdsub_lang)) {
+ d->sub->id = index;
+ d->opts->sub_id = index;
+ mp_msg(MSGT_DEMUX, MSGL_V,
+ "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n",
+ id, val);
+ }
+ else
+ hdr = "Language";
+ }
+ else {
+ for (i = 0; table[i].ogg; i++) {
+ if (!strncasecmp(*cmt, table[i].ogg, strlen(table[i].ogg)) &&
+ (*cmt)[strlen(table[i].ogg)] == '=') {
+ hdr = table[i].mp;
+ val = *cmt + strlen(table[i].ogg) + 1;
+ }
+ }
+ }
+ if (hdr)
+ demux_info_add(d, hdr, val);
+ mp_dbg(MSGT_DEMUX, MSGL_DBG2, " %s: %s\n", hdr, val);
+ cmt++;
}
- if (hdr)
- demux_info_add(d, hdr, val);
- mp_dbg(MSGT_DEMUX, MSGL_DBG2, " %s: %s\n", hdr, val);
- cmt++;
- }
}
/// Calculate the timestamp and add the packet to the demux stream
// return 1 if the packet was added, 0 otherwise
-static int demux_ogg_add_packet(demux_stream_t* ds,ogg_stream_t* os,int id,ogg_packet* pack) {
- demuxer_t* d = ds->demuxer;
- demux_packet_t* dp;
- unsigned char* data;
- float pts = 0;
- int flags = 0;
- int samplesize = 1;
-
- // If packet is an comment header then we try to get comments at first
- if (pack->bytes >= 7 && !memcmp(pack->packet, "\003vorbis", 7))
- {
- vorbis_info vi;
- vorbis_comment vc;
-
- vorbis_info_init(&vi);
- vorbis_comment_init(&vc);
- vi.rate = 1L; // it's checked by vorbis_synthesis_headerin()
- if(vorbis_synthesis_headerin(&vi, &vc, pack) == 0) // if no errors
- demux_ogg_check_comments(d, os, id, &vc);
- vorbis_comment_clear(&vc);
- vorbis_info_clear(&vi);
- }
- if (os->text) {
- if (id == demux_ogg_sub_id(d, d->sub->id)) // don't want to add subtitles to the demuxer for now
- demux_ogg_add_sub(os,pack);
- return 0;
- }
- if (os->speex) {
- // discard first two packets, they contain the header and comment
- if (os->hdr_packets < 2) {
- os->hdr_packets++;
- return 0;
+static int demux_ogg_add_packet(demux_stream_t *ds, ogg_stream_t *os,
+ int id, ogg_packet *pack)
+{
+ demuxer_t *d = ds->demuxer;
+ demux_packet_t *dp;
+ unsigned char *data;
+ float pts = 0;
+ int flags = 0;
+ int samplesize = 1;
+
+ // If packet is an comment header then we try to get comments at first
+ if (pack->bytes >= 7 && !memcmp(pack->packet, "\003vorbis", 7)) {
+ vorbis_info vi;
+ vorbis_comment vc;
+
+ vorbis_info_init(&vi);
+ vorbis_comment_init(&vc);
+ vi.rate = 1L; // it's checked by vorbis_synthesis_headerin()
+ if (vorbis_synthesis_headerin(&vi, &vc, pack) == 0) // if no errors
+ demux_ogg_check_comments(d, os, id, &vc);
+ vorbis_comment_clear(&vc);
+ vorbis_info_clear(&vi);
+ }
+ if (os->text) {
+ if (id == demux_ogg_sub_id(d, d->sub->id)) // don't want to add subtitles to the demuxer for now
+ demux_ogg_add_sub(os, pack);
+ return 0;
+ }
+ if (os->speex) {
+ // discard first two packets, they contain the header and comment
+ if (os->hdr_packets < 2) {
+ os->hdr_packets++;
+ return 0;
+ }
+ } else {
+ // If packet is an header we jump it except for vorbis and theora
+ // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
+ // We jump nothing for FLAC. Ain't this great? Packet contents have to be
+ // handled differently for each and every stream type. The joy! The joy!
+ if (!os->flac && (*pack->packet & PACKET_TYPE_HEADER) &&
+ (ds != d->audio || ((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) &&
+ (ds != d->video || (((sh_video_t*)ds->sh)->format != FOURCC_THEORA)))
+ return 0;
}
- } else
- // If packet is an header we jump it except for vorbis and theora
- // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
- // We jump nothing for FLAC. Ain't this great? Packet contents have to be
- // handled differently for each and every stream type. The joy! The joy!
- if(!os->flac && (*pack->packet & PACKET_TYPE_HEADER) &&
- (ds != d->audio || ((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) &&
- (ds != d->video || (((sh_video_t*)ds->sh)->format != FOURCC_THEORA)))
- return 0;
-
- // For vorbis packet the packet is the data, for other codec we must jump
- // the header
- if(ds == d->audio && ((sh_audio_t*)ds->sh)->format == FOURCC_VORBIS) {
- samplesize = ((sh_audio_t *)ds->sh)->samplesize;
- }
- data = demux_ogg_read_packet(os,pack,&pts,&flags,samplesize);
- if (!data)
- return 0;
- /// Clear subtitles if necessary (for broken files)
- if (sub_clear_text(&ogg_sub, pts)) {
- vo_sub = &ogg_sub;
- vo_osd_changed(OSDTYPE_SUBTITLE);
- }
- /// Send the packet
- dp = new_demux_packet(pack->bytes-(data-pack->packet));
- memcpy(dp->buffer,data,pack->bytes-(data-pack->packet));
- dp->pts = pts;
- dp->flags = flags;
- ds_add_packet(ds,dp);
- mp_msg(MSGT_DEMUX,MSGL_DBG2,"New dp: %p ds=%p pts=%5.3f len=%d flag=%d \n",
- dp, ds, pts, dp->len, flags);
- return 1;
+ // For vorbis packet the packet is the data, for other codec we must jump
+ // the header
+ if (ds == d->audio && ((sh_audio_t*)ds->sh)->format == FOURCC_VORBIS) {
+ samplesize = ((sh_audio_t *)ds->sh)->samplesize;
+ }
+ data = demux_ogg_read_packet(os, pack, &pts, &flags, samplesize);
+ if (!data)
+ return 0;
+
+ /// Clear subtitles if necessary (for broken files)
+ if (sub_clear_text(&ogg_sub, pts)) {
+ vo_sub = &ogg_sub;
+ vo_osd_changed(OSDTYPE_SUBTITLE);
+ }
+ /// Send the packet
+ dp = new_demux_packet(pack->bytes - (data - pack->packet));
+ memcpy(dp->buffer, data, pack->bytes - (data - pack->packet));
+ dp->pts = pts;
+ dp->flags = flags;
+ ds_add_packet(ds, dp);
+ mp_msg(MSGT_DEMUX, MSGL_DBG2,
+ "New dp: %p ds=%p pts=%5.3f len=%d flag=%d \n",
+ dp, ds, pts, dp->len, flags);
+ return 1;
}
/// if -forceidx build a table of all syncpoints to make seeking easier
/// otherwise try to get at least the final_granulepos
static void demux_ogg_scan_stream(demuxer_t *demuxer)
{
- ogg_demuxer_t* ogg_d = demuxer->priv;
- stream_t *s = demuxer->stream;
- ogg_sync_state* sync = &ogg_d->sync;
- ogg_page* page= &ogg_d->page;
- ogg_stream_state* oss;
- ogg_stream_t* os;
- ogg_packet op;
- int np,sid,p,samplesize=1;
- off_t pos, last_pos;
- pos = last_pos = demuxer->movi_start;
-
- // Reset the stream
- stream_seek(s,demuxer->movi_start);
- ogg_sync_reset(sync);
-
- // Get the serial number of the stream we use
- if(demuxer->video->id >= 0) {
- sid = demuxer->video->id;
- }
- else if(demuxer->audio->id >= 0) {
- sid = demuxer->audio->id;
- if(((sh_audio_t*)demuxer->audio->sh)->format == FOURCC_VORBIS) {
- samplesize = ((sh_audio_t*)demuxer->audio->sh)->samplesize;
- }
- }
- else return;
- os = &ogg_d->subs[sid];
- oss = &os->stream;
-
- while(1) {
- np = ogg_sync_pageseek(sync,page);
- if(np < 0) { // We had to skip some bytes
- if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_ERR,"Bad page sync while building syncpoints table (%d)\n",-np);
- pos += -np;
- continue;
- }
- if(np <= 0) { // We need more data
- char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
- int len = stream_read(s,buf,BLOCK_SIZE);
- if(len == 0 && s->eof)
- break;
- ogg_sync_wrote(sync,len);
- continue;
- }
- // The page is ready
- //ogg_sync_pageout(sync,page);
- if(ogg_page_serialno(page) != os->stream.serialno) { // It isn't a page from the stream we want
- pos += np;
- continue;
- }
- if(ogg_stream_pagein(oss,page) != 0) {
- mp_msg(MSGT_DEMUX,MSGL_ERR,"Pagein error ????\n");
- pos += np;
- continue;
+ ogg_demuxer_t *ogg_d = demuxer->priv;
+ stream_t *s = demuxer->stream;
+ ogg_sync_state *sync = &ogg_d->sync;
+ ogg_page *page = &ogg_d->page;
+ ogg_stream_state *oss;
+ ogg_stream_t *os;
+ ogg_packet op;
+ int np, sid, p, samplesize = 1;
+ off_t pos, last_pos;
+
+ pos = last_pos = demuxer->movi_start;
+
+ // Reset the stream
+ stream_seek(s, demuxer->movi_start);
+ ogg_sync_reset(sync);
+
+ // Get the serial number of the stream we use
+ if (demuxer->video->id >= 0) {
+ sid = demuxer->video->id;
+ } else if (demuxer->audio->id >= 0) {
+ sid = demuxer->audio->id;
+ if (((sh_audio_t*)demuxer->audio->sh)->format == FOURCC_VORBIS)
+ samplesize = ((sh_audio_t*)demuxer->audio->sh)->samplesize;
+ } else
+ return;
+ os = &ogg_d->subs[sid];
+ oss = &os->stream;
+
+ while (1) {
+ np = ogg_sync_pageseek(sync, page);
+ if (np < 0) { // We had to skip some bytes
+ if (index_mode == 2)
+ mp_msg(MSGT_DEMUX, MSGL_ERR,
+ "Bad page sync while building syncpoints table (%d)\n",
+ -np);
+ pos += -np;
+ continue;
+ }
+ if (np <= 0) { // We need more data
+ char *buf = ogg_sync_buffer(sync, BLOCK_SIZE);
+ int len = stream_read(s, buf, BLOCK_SIZE);
+
+ if (len == 0 && s->eof)
+ break;
+ ogg_sync_wrote(sync, len);
+ continue;
+ }
+ // The page is ready
+ //ogg_sync_pageout(sync, page);
+ if (ogg_page_serialno(page) != os->stream.serialno) { // It isn't a page from the stream we want
+ pos += np;
+ continue;
+ }
+ if (ogg_stream_pagein(oss, page) != 0) {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "Pagein error ????\n");
+ pos += np;
+ continue;
+ }
+ p = 0;
+ while (ogg_stream_packetout(oss, &op) == 1) {
+ float pts;
+ int flags;
+
+ demux_ogg_read_packet(os, &op, &pts, &flags, samplesize);
+ if (op.granulepos >= 0) {
+ ogg_d->final_granulepos = op.granulepos;
+ if (ogg_d->initial_granulepos == MP_NOPTS_VALUE && (flags & 1)) {
+ ogg_d->initial_granulepos = op.granulepos;
+ if (index_mode != 2 && ogg_d->pos < demuxer->movi_end - 2 * 270000) {
+ //the 270000 are just a wild guess
+ stream_seek(s, FFMAX(ogg_d->pos, demuxer->movi_end - 270000));
+ ogg_sync_reset(sync);
+ continue;
+ }
+ }