diff options
Diffstat (limited to 'libmpdemux')
-rw-r--r-- | libmpdemux/aviheader.c | 2 | ||||
-rw-r--r-- | libmpdemux/demux_avi.c | 15 | ||||
-rw-r--r-- | libmpdemux/demux_avs.c | 2 | ||||
-rw-r--r-- | libmpdemux/demux_demuxers.c | 3 | ||||
-rw-r--r-- | libmpdemux/demux_lavf.c | 16 | ||||
-rw-r--r-- | libmpdemux/demux_mkv.c | 461 | ||||
-rw-r--r-- | libmpdemux/demux_mov.c | 5 | ||||
-rw-r--r-- | libmpdemux/demux_mpg.c | 6 | ||||
-rw-r--r-- | libmpdemux/demux_nemesi.c | 2 | ||||
-rw-r--r-- | libmpdemux/demux_ogg.c | 11 | ||||
-rw-r--r-- | libmpdemux/demux_pva.c | 2 | ||||
-rw-r--r-- | libmpdemux/demux_rtp.cpp | 10 | ||||
-rw-r--r-- | libmpdemux/demuxer.c | 168 | ||||
-rw-r--r-- | libmpdemux/demuxer.h | 83 | ||||
-rw-r--r-- | libmpdemux/ebml.h | 3 | ||||
-rw-r--r-- | libmpdemux/mp3_hdr.c | 3 | ||||
-rw-r--r-- | libmpdemux/parse_mp4.c | 2 | ||||
-rw-r--r-- | libmpdemux/stheader.h | 40 |
18 files changed, 440 insertions, 394 deletions
diff --git a/libmpdemux/aviheader.c b/libmpdemux/aviheader.c index 85a84e8ca3..fa7f27c4fc 100644 --- a/libmpdemux/aviheader.c +++ b/libmpdemux/aviheader.c @@ -42,7 +42,7 @@ static int odml_get_vstream_id(int id, unsigned char res[]) return 0; } -int avi_idx_cmp(const void *elem1,const void *elem2) { +static int avi_idx_cmp(const void *elem1,const void *elem2) { register off_t a = AVI_IDX_OFFSET((AVIINDEXENTRY *)elem1); register off_t b = AVI_IDX_OFFSET((AVIINDEXENTRY *)elem2); return (a > b) - (b > a); diff --git a/libmpdemux/demux_avi.c b/libmpdemux/demux_avi.c index fa1fc91e48..9695fcb556 100644 --- a/libmpdemux/demux_avi.c +++ b/libmpdemux/demux_avi.c @@ -24,7 +24,9 @@ extern const demuxer_desc_t demuxer_desc_avi_nini; int pts_from_bps=1; // Select ds from ID -demux_stream_t* demux_avi_select_stream(demuxer_t *demux,unsigned int id){ +static demux_stream_t* demux_avi_select_stream(demuxer_t *demux, + unsigned int id) +{ int stream_id=avi_stream_id(id); @@ -277,7 +279,7 @@ do{ // return value: // 0 = EOF or no stream found // 1 = successfully read a packet -int demux_avi_fill_buffer_ni(demuxer_t *demux,demux_stream_t* ds){ +static int demux_avi_fill_buffer_ni(demuxer_t *demux,demux_stream_t* ds){ avi_priv_t *priv=demux->priv; unsigned int id=0; unsigned int len; @@ -341,7 +343,7 @@ do{ // return value: // 0 = EOF or no stream found // 1 = successfully read a packet -int demux_avi_fill_buffer_nini(demuxer_t *demux,demux_stream_t* ds){ +static int demux_avi_fill_buffer_nini(demuxer_t *demux,demux_stream_t* ds){ avi_priv_t *priv=demux->priv; unsigned int id=0; unsigned int len; @@ -572,7 +574,7 @@ static demuxer_t* demux_open_avi(demuxer_t* demuxer){ } -void demux_seek_avi(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){ +static void demux_seek_avi(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags){ avi_priv_t *priv=demuxer->priv; demux_stream_t *d_audio=demuxer->audio; demux_stream_t *d_video=demuxer->video; @@ -745,7 +747,7 @@ void demux_seek_avi(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int } -void demux_close_avi(demuxer_t *demuxer) { +static void demux_close_avi(demuxer_t *demuxer) { avi_priv_t* priv=demuxer->priv; if(!priv) @@ -837,6 +839,7 @@ static int avi_check_file(demuxer_t *demuxer) static demuxer_t* demux_open_hack_avi(demuxer_t *demuxer) { + struct MPOpts *opts = demuxer->opts; sh_audio_t* sh_a; demuxer = demux_open_avi(demuxer); @@ -851,7 +854,7 @@ static demuxer_t* demux_open_hack_avi(demuxer_t *demuxer) stream_t* s; demuxer_t *od; s = new_ds_stream(demuxer->audio); - od = new_demuxer(s,DEMUXER_TYPE_OGG,-1,-2,-2,NULL); + od = new_demuxer(opts, s,DEMUXER_TYPE_OGG,-1,-2,-2,NULL); if(!demux_ogg_open(od)) { mp_msg( MSGT_DEMUXER,MSGL_ERR,MSGTR_ErrorOpeningOGGDemuxer); free_stream(s); diff --git a/libmpdemux/demux_avs.c b/libmpdemux/demux_avs.c index 8d2ac82046..444e06c90c 100644 --- a/libmpdemux/demux_avs.c +++ b/libmpdemux/demux_avs.c @@ -85,7 +85,7 @@ typedef struct tagAVS imp_avs_get_audio avs_get_audio; } AVS_T; -AVS_T *initAVS(const char *filename) +static AVS_T *initAVS(const char *filename) { AVS_T *AVS = malloc (sizeof(AVS_T)); AVS_Value arg0 = avs_new_value_string(filename); diff --git a/libmpdemux/demux_demuxers.c b/libmpdemux/demux_demuxers.c index a5f87e601b..dc04ecffd0 100644 --- a/libmpdemux/demux_demuxers.c +++ b/libmpdemux/demux_demuxers.c @@ -8,6 +8,7 @@ #include "stream/stream.h" #include "demuxer.h" #include "stheader.h" +#include "talloc.h" typedef struct dd_priv { demuxer_t* vd; @@ -21,7 +22,7 @@ demuxer_t* new_demuxers_demuxer(demuxer_t* vd, demuxer_t* ad, demuxer_t* sd) { demuxer_t* ret; dd_priv_t* priv; - ret = calloc(1,sizeof(demuxer_t)); + ret = talloc_zero(NULL, struct demuxer); priv = malloc(sizeof(dd_priv_t)); priv->vd = vd; diff --git a/libmpdemux/demux_lavf.c b/libmpdemux/demux_lavf.c index 5383e161c8..21f3d21155 100644 --- a/libmpdemux/demux_lavf.c +++ b/libmpdemux/demux_lavf.c @@ -22,8 +22,10 @@ #include <stdlib.h> // #include <unistd.h> #include <limits.h> +#include <stdbool.h> #include "config.h" +#include "options.h" #include "mp_msg.h" #include "help_mp.h" #include "av_opts.h" @@ -43,9 +45,6 @@ #define PROBE_BUF_SIZE (32*1024) -extern char *audio_lang; -extern char *dvdsub_lang; -extern int dvdsub_id; static unsigned int opt_probesize = 0; static unsigned int opt_analyzeduration = 0; static char *opt_format; @@ -418,6 +417,7 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i) { } static demuxer_t* demux_open_lavf(demuxer_t *demuxer){ + struct MPOpts *opts = demuxer->opts; AVFormatContext *avfc; AVFormatParameters ap; const AVOption *opt; @@ -433,7 +433,7 @@ static demuxer_t* demux_open_lavf(demuxer_t *demuxer){ if (opt_cryptokey) parse_cryptokey(avfc, opt_cryptokey); - if (user_correct_pts != 0) + if (opts->user_correct_pts != 0) avfc->flags |= AVFMT_FLAG_GENPTS; if (index_mode == 0) avfc->flags |= AVFMT_FLAG_IGNIDX; @@ -534,6 +534,8 @@ static demuxer_t* demux_open_lavf(demuxer_t *demuxer){ demuxer->video->id=-2; // audio-only } //else if (best_video > 0 && demuxer->video->id == -1) demuxer->video->id = best_video; + demuxer->accurate_seek = true; + return demuxer; } @@ -609,10 +611,14 @@ static void demux_seek_lavf(demuxer_t *demuxer, float rel_seek_secs, float audio mp_msg(MSGT_DEMUX,MSGL_DBG2,"demux_seek_lavf(%p, %f, %f, %d)\n", demuxer, rel_seek_secs, audio_delay, flags); if (flags & SEEK_ABSOLUTE) { - priv->last_pts = priv->avfc->start_time; + priv->last_pts = 0; } else { if (rel_seek_secs < 0) avsflags = AVSEEK_FLAG_BACKWARD; } + if (flags & SEEK_FORWARD) + avsflags = 0; + else if (flags & SEEK_BACKWARD) + avsflags = AVSEEK_FLAG_BACKWARD; if (flags & SEEK_FACTOR) { if (priv->avfc->duration == 0 || priv->avfc->duration == AV_NOPTS_VALUE) return; diff --git a/libmpdemux/demux_mkv.c b/libmpdemux/demux_mkv.c index 6d4429377c..e9853bc3e4 100644 --- a/libmpdemux/demux_mkv.c +++ b/libmpdemux/demux_mkv.c @@ -12,7 +12,10 @@ #include <stdio.h> #include <ctype.h> #include <inttypes.h> +#include <stdbool.h> +#include "talloc.h" +#include "options.h" #include "stream/stream.h" #include "demuxer.h" #include "stheader.h" @@ -55,13 +58,12 @@ static const unsigned char sipr_swaps[38][2]={ #define ATRC_FLAVORS 8 #define COOK_FLAVORS 34 static const int sipr_fl2bps[SIPR_FLAVORS] = {813, 1062, 625, 2000}; -static const int atrc_fl2bps[ATRC_FLAVORS] = - {8269, 11714, 13092, 16538, 18260, 22050, 33075, 44100}; -static const int cook_fl2bps[COOK_FLAVORS] = - { 1000, 1378, 2024, 2584, 4005, 5513, 8010, 4005, 750, 2498, - 4048, 5513, 8010, 11973, 8010, 2584, 4005, 2067, 2584, 2584, - 4005, 4005, 5513, 5513, 8010, 12059, 1550, 8010, 12059, 5513, - 12016, 16408, 22911, 33506}; +static const int atrc_fl2bps[ATRC_FLAVORS] = {8269, 11714, 13092, 16538, 18260, 22050, 33075, 44100}; +static const int cook_fl2bps[COOK_FLAVORS] = { + 1000, 1378, 2024, 2584, 4005, 5513, 8010, 4005, 750, 2498, + 4048, 5513, 8010, 11973, 8010, 2584, 4005, 2067, 2584, 2584, + 4005, 4005, 5513, 5513, 8010, 12059, 1550, 8010, 12059, 5513, + 12016, 16408, 22911, 33506}; typedef struct { @@ -93,7 +95,7 @@ typedef struct mkv_track int default_track; - void *private_data; + unsigned char *private_data; unsigned int private_size; /* stuff for realmedia */ @@ -151,8 +153,7 @@ typedef struct mkv_demuxer mkv_track_t **tracks; int num_tracks; - uint64_t tc_scale, cluster_tc, first_tc; - int has_first_tc; + uint64_t tc_scale, cluster_tc; uint64_t cluster_size; uint64_t blockgroup_size; @@ -171,8 +172,6 @@ typedef struct mkv_demuxer int64_t skip_to_timecode; int v_skip_to_keyframe, a_skip_to_keyframe; - int64_t stop_timecode; - int last_aid; int audio_tracks[MAX_A_STREAMS]; } mkv_demuxer_t; @@ -182,20 +181,16 @@ typedef struct mkv_demuxer #define RAPROPERTIES4_SIZE 56 #define RAPROPERTIES5_SIZE 70 -/* for e.g. "-slang ger" */ -extern char *dvdsub_lang; -extern char *audio_lang; -extern int dvdsub_id; - /** * \brief ensures there is space for at least one additional element * \param array array to grow * \param nelem current number of elements in array * \param elsize size of one array element */ -static void grow_array(void **array, int nelem, size_t elsize) { +static void *grow_array(void *array, int nelem, size_t elsize) { if (!(nelem & 31)) - *array = realloc(*array, (nelem + 32) * elsize); + array = realloc(array, (nelem + 32) * elsize); + return array; } static mkv_track_t * @@ -220,8 +215,9 @@ add_cluster_position (mkv_demuxer_t *mkv_d, uint64_t position) if (mkv_d->cluster_positions[i] == position) return; - grow_array(&mkv_d->cluster_positions, mkv_d->num_cluster_pos, - sizeof(uint64_t)); + mkv_d->cluster_positions = grow_array(mkv_d->cluster_positions, + mkv_d->num_cluster_pos, + sizeof(uint64_t)); mkv_d->cluster_positions[mkv_d->num_cluster_pos++] = position; } @@ -378,52 +374,67 @@ lzo_fail: } -static int -demux_mkv_read_info (demuxer_t *demuxer) +static int demux_mkv_read_info(demuxer_t *demuxer) { - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - stream_t *s = demuxer->stream; - uint64_t length, l; - int il; - uint64_t tc_scale = 1000000; - long double duration = 0.; - - length = ebml_read_length (s, NULL); - while (length > 0) - { - switch (ebml_read_id (s, &il)) - { + mkv_demuxer_t *mkv_d = demuxer->priv; + stream_t *s = demuxer->stream; + uint64_t length, l; + int i; + uint64_t tc_scale = 1000000; + long double duration = 0.; + + length = ebml_read_length(s, NULL); + while (length > 0) { + uint32_t id = ebml_read_id(s, &i); + length -= i; + switch (id) { case MATROSKA_ID_TIMECODESCALE: - { - uint64_t num = ebml_read_uint (s, &l); - if (num == EBML_UINT_INVALID) - return 1; - tc_scale = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + timecode scale: %"PRIu64"\n", + tc_scale = ebml_read_uint(s, &l); + length -= l; + if (tc_scale == EBML_UINT_INVALID) + return 1; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + timecode scale: %"PRIu64"\n", tc_scale); break; - } case MATROSKA_ID_DURATION: - { - long double num = ebml_read_float (s, &l); - if (num == EBML_FLOAT_INVALID) - return 1; - duration = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + duration: %.3Lfs\n", - duration * tc_scale / 1000000000.0); + duration = ebml_read_float(s, &l); + length -= l; + if (duration == EBML_FLOAT_INVALID) + return 1; + break; + + case MATROSKA_ID_SEGMENTUID:; + l = ebml_read_length(s, &i); + length -= i; + if (l != sizeof(demuxer->matroska_data.segment_uid)) { + mp_msg(MSGT_DEMUX, MSGL_INFO, + "[mkv] segment uid invalid length %"PRIu64"\n", l); + stream_skip(s, l); + } else { + stream_read(s, demuxer->matroska_data.segment_uid, l); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + segment uid"); + for (int i = 0; i < l; i++) + mp_msg(MSGT_DEMUX, MSGL_V, " %02x", + demuxer->matroska_data.segment_uid[i]); + mp_msg(MSGT_DEMUX, MSGL_V, "\n"); + } + length -= l; break; - } default: - ebml_read_skip (s, &l); - break; + ebml_read_skip(s, &l); + length -= l; + break; } - length -= l + il; } - mkv_d->tc_scale = tc_scale; - mkv_d->duration = duration * tc_scale / 1000000000.0; - return 0; + mkv_d->tc_scale = tc_scale; + mkv_d->duration = duration * tc_scale / 1000000000.0; + if (duration) + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + duration: %.3fs\n", + mkv_d->duration); + + return 0; } /** @@ -1064,7 +1075,8 @@ demux_mkv_read_cues (demuxer_t *demuxer) if (time != EBML_UINT_INVALID && track != EBML_UINT_INVALID && pos != EBML_UINT_INVALID) { - grow_array(&mkv_d->indexes, mkv_d->num_indexes, sizeof(mkv_index_t)); + mkv_d->indexes = grow_array(mkv_d->indexes, mkv_d->num_indexes, + sizeof(mkv_index_t)); mkv_d->indexes[mkv_d->num_indexes].tnum = track; mkv_d->indexes[mkv_d->num_indexes].timecode = time; mkv_d->indexes[mkv_d->num_indexes].filepos =mkv_d->segment_start+pos; @@ -1079,140 +1091,175 @@ demux_mkv_read_cues (demuxer_t *demuxer) return 0; } -static int -demux_mkv_read_chapters (demuxer_t *demuxer) +static uint64_t read_one_chapter(struct demuxer *demuxer, stream_t *s) { - stream_t *s = demuxer->stream; - uint64_t length, l; - int il; - - if (demuxer->chapters) - { - ebml_read_skip (s, NULL); - return 0; - } - - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing chapters ] ---------\n"); - length = ebml_read_length (s, NULL); - - while (length > 0) - { - switch (ebml_read_id (s, &il)) - { - case MATROSKA_ID_EDITIONENTRY: - { - uint64_t len; - int i; - - len = ebml_read_length (s, &i); - l = len + i; + uint64_t len, l; + uint64_t start = 0, end = 0; + struct matroska_chapter chapter = {}; + char *name = 0; + int i; + uint32_t id; + + len = ebml_read_length(s, &i); + uint64_t bytes_read = len + i; + + while (len > 0) { + id = ebml_read_id(s, &i); + len -= i; + switch (id) { + case MATROSKA_ID_CHAPTERTIMESTART: + start = ebml_read_uint(s, &l) / 1000000; + len -= l; + break; - while (len > 0) - { - uint64_t l; - int il; + case MATROSKA_ID_CHAPTERTIMEEND: + end = ebml_read_uint(s, &l) / 1000000; + len -= l; + break; - switch (ebml_read_id (s, &il)) - { - case MATROSKA_ID_CHAPTERATOM: - { - uint64_t len, start=0, end=0; - char* name = 0; - int i; - int cid; + case MATROSKA_ID_CHAPTERDISPLAY:; + uint64_t displaylen = ebml_read_length(s, &i); + len -= displaylen + i; + while (displaylen > 0) { + id = ebml_read_id(s, &i); + displaylen -= i; + switch (id) { + case MATROSKA_ID_CHAPSTRING: + name = ebml_read_utf8(s, &l); + break; + default: + ebml_read_skip(s, &l); + break; + } + displaylen -= l; + } + break; - len = ebml_read_length (s, &i); - l = len + i; + case MATROSKA_ID_CHAPTERSEGMENTUID: + l = ebml_read_length(s, &i); + len -= l + i; + if (l != sizeof(chapter.segment_uid)) { + mp_msg(MSGT_DEMUX, MSGL_INFO, + "[mkv] chapter segment uid invalid length %"PRIu64"\n", + l); + stream_skip(s, l); + } else { + stream_read(s, chapter.segment_uid, l); + chapter.has_segment_uid = true; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Chapter segment uid "); + for (int i = 0; i < l; i++) + mp_msg(MSGT_DEMUX, MSGL_V, "%02x ", chapter.segment_uid[i]); + mp_msg(MSGT_DEMUX, MSGL_V, "\n"); + } + break; - while (len > 0) - { - uint64_t l; - int il; + default: + ebml_read_skip(s, &l); + len -= l; + break; + } + } - switch (ebml_read_id (s, &il)) - { - case MATROSKA_ID_CHAPTERTIMESTART: - start = ebml_read_uint (s, &l) / 1000000; - break; + if (!name) + name = strdup("(unnamed)"); + + int cid = demuxer_add_chapter(demuxer, name, start, end); + struct matroska_data *m = &demuxer->matroska_data; + m->ordered_chapters = talloc_realloc(demuxer, m->ordered_chapters, + struct matroska_chapter, + m->num_ordered_chapters + 1); + chapter.start = start; + chapter.end = end; + chapter.name = talloc_strdup(m->ordered_chapters, name); + // Will be undone later if this is a normal chapter rather than ordered + m->ordered_chapters[m->num_ordered_chapters] = chapter; + m->num_ordered_chapters++; + + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Chapter %u from %02d:%02d:%02d." + "%03d to %02d:%02d:%02d.%03d, %s\n", + cid, + (int) (start / 60 / 60 / 1000), + (int) ((start / 60 / 1000) % 60), + (int) ((start / 1000) % 60), + (int) (start % 1000), + (int) (end / 60 / 60 / 1000), + (int) ((end / 60 / 1000) % 60), + (int) ((end / 1000) % 60), + (int) (end % 1000), name); + + free(name); + return bytes_read; +} - case MATROSKA_ID_CHAPTERTIMEEND: - end = ebml_read_uint (s, &l) / 1000000; - break; +static int demux_mkv_read_chapters(struct demuxer *demuxer) +{ + stream_t *s = demuxer->stream; + uint64_t length, l; + int i; + uint32_t id; - case MATROSKA_ID_CHAPTERDISPLAY: - { - uint64_t len; - int i; - - len = ebml_read_length (s, &i); - l = len + i; - while (len > 0) - { - uint64_t l; - int il; - - switch (ebml_read_id (s, &il)) - { - case MATROSKA_ID_CHAPSTRING: - name = ebml_read_utf8 (s, &l); - break; - default: - ebml_read_skip (s, &l); - break; - } - len -= l + il; - } - } - break; + if (demuxer->chapters) { + ebml_read_skip(s, NULL); + return 0; + } - default: - ebml_read_skip (s, &l); - break; - } - len -= l + il; - } + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing chapters ] ---------\n"); + length = ebml_read_length(s, NULL); - if (!name) - name = strdup("(unnamed)"); - - cid = demuxer_add_chapter(demuxer, name, start, end); - - mp_msg(MSGT_DEMUX, MSGL_V, - "[mkv] Chapter %u from %02d:%02d:%02d." - "%03d to %02d:%02d:%02d.%03d, %s\n", - cid, - (int) (start / 60 / 60 / 1000), - (int) ((start / 60 / 1000) % 60), - (int) ((start / 1000) % 60), - (int) (start % 1000), - (int) (end / 60 / 60 / 1000), - (int) ((end / 60 / 1000) % 60), - (int) ((end / 1000) % 60), - (int) (end % 1000), name); - - free(name); - break; - } + bool have_edition = false; + while (length > 0) { + id = ebml_read_id(s, &i); + length -= i; + switch (id) { + case MATROSKA_ID_EDITIONENTRY: + if (have_edition) { + mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Multiple edition entries" + " - ignoring all but first!\n"); + ebml_read_skip(s, &l); + length -= l; + break; + } + have_edition = true; + uint64_t editionlen = ebml_read_length(s, &i); + length -= editionlen + i; + bool ordered = false; + while (editionlen > 0) { + id = ebml_read_id(s, &i); + editionlen -= i; + switch (id) { + case MATROSKA_ID_CHAPTERATOM: + l = read_one_chapter(demuxer, s); + break; + case MATROSKA_ID_EDITIONFLAGORDERED: + ordered = ebml_read_uint(s, &l); + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] Ordered chapter flag: %d\n", ordered); + break; - default: - ebml_read_skip (s, &l); + default: + ebml_read_skip(s, &l); break; - } - len -= l + il; - } + } + editionlen -= l; + } + if (!ordered) { + // The chapters should be interpreted as normal ones, + // so undo the addition of this information. + talloc_free(demuxer->matroska_data.ordered_chapters); + demuxer->matroska_data.ordered_chapters = NULL; + demuxer->matroska_data.num_ordered_chapters = 0; + } break; - } default: - ebml_read_skip (s, &l); - break; + ebml_read_skip(s, &l); + length -= l; + break; } - - length -= l + il; } - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] \\---- [ parsing chapters ] ---------\n"); - return 0; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] \\---- [ parsing chapters ] ---------\n"); + return 0; } static int @@ -1514,6 +1561,7 @@ static const videocodec_info_t vinfo[] = { static int demux_mkv_open_video (demuxer_t *demuxer, mkv_track_t *track, int vid) { + struct MPOpts *opts = demuxer->opts; BITMAPINFOHEADER *bih; void *ImageDesc = NULL; sh_video_t *sh_v; @@ -1624,7 +1672,7 @@ demux_mkv_open_video (demuxer_t *demuxer, mkv_track_t *track, int vid) bih = realloc (bih, bih->biSize); memcpy (bih + 1, track->private_data, track->private_size); } - track->reorder_timecodes = user_correct_pts == 0; + track->reorder_timecodes = opts->user_correct_pts == 0; if (!vi->id) { mp_msg (MSGT_DEMUX,MSGL_WARN, MSGTR_MPDEMUX_MKV_UnknownCodecID, track->codec_id, track->tnum); @@ -1950,13 +1998,13 @@ demux_mkv_open_audio (demuxer_t *demuxer, mkv_track_t *track, int aid) if (track->a_formattag == mmioFOURCC('f', 'L', 'a', 'C')) { - ptr = (unsigned char *)track->private_data; + ptr = track->private_data; size = track->private_size; } else { sh_a->format = mmioFOURCC('f', 'L', 'a', 'C'); - ptr = (unsigned char *) track->private_data + ptr = track->private_data + sizeof (WAVEFORMATEX); size = track->private_size - sizeof (WAVEFORMATEX); } @@ -2026,8 +2074,6 @@ demux_mkv_open_sub (demuxer_t *demuxer, mkv_track_t *track, int sid) return 0; } -static void demux_mkv_seek (demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags); - static int demux_mkv_open (demuxer_t *demuxer) { @@ -2117,8 +2163,6 @@ demux_mkv_open (demuxer_t *demuxer) uint64_t num = ebml_read_uint (s, NULL); if (num == EBML_UINT_INVALID) return 0; - mkv_d->first_tc = num * mkv_d->tc_scale / 1000000.0; - mkv_d->has_first_tc = 1; } stream_seek (s, p - 4); cont = 1; @@ -2222,22 +2266,6 @@ demux_mkv_open (demuxer_t *demuxer) } } - if (demuxer->chapters) - { - for (i=0; i < (int)demuxer->num_chapters; i++) - { - demuxer->chapters[i].start -= mkv_d->first_tc; - demuxer->chapters[i].end -= mkv_d->first_tc; - } - if (dvd_last_chapter > 0 && dvd_last_chapter <= demuxer->num_chapters) - { - if (demuxer->chapters[dvd_last_chapter-1].end != 0) - mkv_d->stop_timecode = demuxer->chapters[dvd_last_chapter-1].end; - else if (dvd_last_chapter + 1 <= demuxer->num_chapters) - mkv_d->stop_timecode = demuxer->chapters[dvd_last_chapter].start; - } - } - if (s->end_pos == 0 || (mkv_d->indexes == NULL && index_mode < 0)) demuxer->seekable = 0; else @@ -2247,6 +2275,8 @@ demux_mkv_open (demuxer_t *demuxer) demuxer->seekable = 1; } + demuxer->accurate_seek = true; + return DEMUXER_TYPE_MATROSKA; } @@ -2625,13 +2655,9 @@ handle_block (demuxer_t *demuxer, uint8_t *block, uint64_t length, return 0; block += old_length - length; - tc = ((time*mkv_d->tc_scale+mkv_d->cluster_tc) /1000000.0 - mkv_d->first_tc); + tc = ((time*mkv_d->tc_scale+mkv_d->cluster_tc) /1000000.0); if (tc < 0) tc = 0; - if (mkv_d->stop_timecode > 0 && tc > mkv_d->stop_timecode) { - free(lace_size); - return -1; - } current_pts = tc / 1000.0; for (i=0; i<mkv_d->num_tracks; i++) @@ -2854,11 +2880,6 @@ demux_mkv_fill_buffer (demuxer_t *demuxer, demux_stream_t *ds) uint64_t num = ebml_read_uint (s, &l); if (num == EBML_UINT_INVALID) return 0; - if (!mkv_d->has_first_tc) - { - mkv_d->first_tc = num * mkv_d->tc_scale / 1000000.0; - mkv_d->has_first_tc = 1; - } mkv_d->cluster_tc = num * mkv_d->tc_scale; break; } @@ -2914,6 +2935,16 @@ demux_mkv_fill_buffer (demuxer_t *demuxer, demux_stream_t *ds) static void demux_mkv_seek (demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags) { + if (!(flags & (SEEK_BACKWARD | SEEK_FORWARD))) { + if (flags & SEEK_ABSOLUTE || rel_seek_secs < 0) + flags |= SEEK_BACKWARD; + else + flags |= SEEK_FORWARD; + } + // Adjust the target a little bit to catch cases where the target position + // specifies a keyframe with high, but not perfect, precision. + rel_seek_secs += flags & SEEK_FORWARD ? -0.001 : 0.001; + free_cached_dps (demuxer); if (!(flags & SEEK_FACTOR)) /* time in secs */ { @@ -2968,12 +2999,12 @@ demux_mkv_seek (demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int for (i=0; i < mkv_d->num_cluster_pos; i++) { diff = mkv_d->cluster_positions[i] - target_filepos; - if (rel_seek_secs < 0 && diff < 0 && -diff < min_diff) + if (flags & SEEK_BACKWARD && diff < 0 && -diff < min_diff) { cluster_pos = mkv_d->cluster_positions[i]; min_diff = -diff; } - else if (rel_seek_secs > 0 + else if (flags & SEEK_FORWARD && (diff < 0 ? -1 * diff : diff) < min_diff) { cluster_pos = mkv_d->cluster_positions[i]; @@ -2994,17 +3025,17 @@ demux_mkv_seek (demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int for (i=0; i < mkv_d->num_indexes; i++) if (mkv_d->indexes[i].tnum == seek_id) { - diff = target_timecode + mkv_d->first_tc - + diff = target_timecode - (int64_t) mkv_d->indexes[i].timecode * mkv_d->tc_scale / 1000000.0; - if ((flags & SEEK_ABSOLUTE || target_timecode <= mkv_d->last_pts*1000)) { - // Absolute seek or seek backward: find the last index - // position before target time + if (flags & SEEK_BACKWARD) { + // Seek backward: find the last index position + // before target time if (diff < 0 || diff >= min_diff) continue; } else { - // Relative seek forward: find the first index position + // Seek forward: find the first index position // after target time. If no such index exists, find last // position between current position and target time. if (diff <= 0) { @@ -3028,8 +3059,10 @@ demux_mkv_seek (demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int if (demuxer->video->id >= 0) mkv_d->v_skip_to_keyframe = 1; - if (rel_seek_secs > 0.0) + if (flags & SEEK_FORWARD) mkv_d->skip_to_timecode = target_timecode; + else + mkv_d->skip_to_timecode = 0; mkv_d->a_skip_to_keyframe = 1; demux_mkv_fill_buffer(demuxer, NULL); diff --git a/libmpdemux/demux_mov.c b/libmpdemux/demux_mov.c index bcb249b732..ecc23f2cc5 100644 --- a/libmpdemux/demux_mov.c +++ b/libmpdemux/demux_mov.c @@ -144,7 +144,7 @@ typedef struct { void* desc; // image/sound/etc description (pointer to ImageDescription etc) } mov_track_t; -void mov_build_index(mov_track_t* trak,int timescale){ +static void mov_build_index(mov_track_t* trak,int timescale){ int i,j,s; int last=trak->chunks_size; unsigned int pts=0; @@ -1917,6 +1917,7 @@ static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id, } static demuxer_t* mov_read_header(demuxer_t* demuxer){ + struct MPOpts *opts = demuxer->opts; mov_priv_t* priv=demuxer->priv; int t_no; int best_a_id=-1, best_a_len=0; @@ -1992,7 +1993,7 @@ static demuxer_t* mov_read_header(demuxer_t* demuxer){ demuxer->video->id = t_no; s = new_ds_stream(demuxer->video); - od = demux_open(s, DEMUXER_TYPE_MPEG_PS, -1, -1, -1, NULL); + od = demux_open(opts, s, DEMUXER_TYPE_MPEG_PS, -1, -1, -1, NULL); if(od) return new_demuxers_demuxer(od, od, od); demuxer->video->id = -2; //new linked demuxer couldn't be allocated break; diff --git a/libmpdemux/demux_mpg.c b/libmpdemux/demux_mpg.c index 8edb6e7a1e..489821f878 100644 --- a/libmpdemux/demux_mpg.c +++ b/libmpdemux/demux_mpg.c @@ -794,7 +794,7 @@ static int demux_mpg_gxf_fill_buffer(demuxer_t *demux, demux_stream_t *ds) { return 1; } -int demux_mpg_fill_buffer(demuxer_t *demux, demux_stream_t *ds){ +static int demux_mpg_fill_buffer(demuxer_t *demux, demux_stream_t *ds){ unsigned int head=0; int skipped=0; int max_packs=256; // 512kbyte @@ -881,7 +881,7 @@ do{ void skip_audio_frame(sh_audio_t *sh_audio); -void demux_seek_mpg(demuxer_t *demuxer,float rel_seek_secs,float audio_delay, int flags){ +static void demux_seek_mpg(demuxer_t *demuxer,float rel_seek_secs,float audio_delay, int flags){ demux_stream_t *d_audio=demuxer->audio; demux_stream_t *d_video=demuxer->video; sh_audio_t *sh_audio=d_audio->sh; @@ -987,7 +987,7 @@ void demux_seek_mpg(demuxer_t *demuxer,float rel_seek_secs,float audio_delay, in } } -int demux_mpg_control(demuxer_t *demuxer,int cmd, void *arg){ +static int demux_mpg_control(demuxer_t *demuxer,int cmd, void *arg){ mpg_demuxer_t *mpg_d=(mpg_demuxer_t*)demuxer->priv; switch(cmd) { diff --git a/libmpdemux/demux_nemesi.c b/libmpdemux/demux_nemesi.c index c1ed7f1089..704f14cf81 100644 --- a/libmpdemux/demux_nemesi.c +++ b/libmpdemux/demux_nemesi.c @@ -455,7 +455,7 @@ static void demux_seek_rtp(demuxer_t *demuxer, float rel_seek_secs, mp_msg(MSGT_DEMUX, MSGL_ERR, "Unsupported seek type\n"); } -static int demux_rtp_control(struct demuxer_st *demuxer, int cmd, void *arg) +static int demux_rtp_control(struct demuxer *demuxer, int cmd, void *arg) { Nemesi_DemuxerStreamData * ndsd = demuxer->priv; rtsp_ctrl * ctl = ndsd->rtsp; diff --git a/libmpdemux/demux_ogg.c b/libmpdemux/demux_ogg.c index 2561714517..013bff5a76 100644 --- a/libmpdemux/demux_ogg.c +++ b/libmpdemux/demux_ogg.c @@ -8,6 +8,7 @@ #include <math.h> #include <inttypes.h> +#include "options.h" #include "mp_msg.h" #include "help_mp.h" #include "stream/stream.h" @@ -146,7 +147,6 @@ typedef struct ogg_demuxer { #define PACKET_IS_SYNCPOINT 0x08 extern char *dvdsub_lang, *audio_lang; -extern int dvdsub_id; //-------- subtitle support - should be moved to decoder layer, and queue // - subtitles up in demuxer buffer... @@ -158,7 +158,7 @@ extern int dvdsub_id; static subtitle ogg_sub; //FILE* subout; -void demux_ogg_add_sub (ogg_stream_t* os,ogg_packet* pack) { +static void demux_ogg_add_sub (ogg_stream_t* os,ogg_packet* pack) { int lcv; char *packet = pack->packet; @@ -395,7 +395,7 @@ static void demux_ogg_check_comments(demuxer_t *d, ogg_stream_t *os, int id, vor if (os->text && d->sub->id < 0 && demux_ogg_check_lang(val, dvdsub_lang)) { d->sub->id = index; - dvdsub_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 @@ -491,7 +491,7 @@ static int demux_ogg_add_packet(demux_stream_t* ds,ogg_stream_t* os,int id,ogg_p /// if -forceidx build a table of all syncpoints to make seeking easier /// otherwise try to get at least the final_granulepos -void demux_ogg_scan_stream(demuxer_t* demuxer) { +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; @@ -1216,6 +1216,7 @@ static int demux_ogg_fill_buffer(demuxer_t *d, demux_stream_t *dsds) { /// For avi with Ogg audio stream we have to create an ogg demuxer for this // stream, then we join the avi and ogg demuxer with a demuxers demuxer demuxer_t* init_avi_with_ogg(demuxer_t* demuxer) { + struct MPOpts *opts = demuxer->opts; demuxer_t *od; ogg_demuxer_t *ogg_d; stream_t* s; @@ -1277,7 +1278,7 @@ demuxer_t* init_avi_with_ogg(demuxer_t* demuxer) { // Create the ds_stream and the ogg demuxer s = new_ds_stream(demuxer->audio); - od = new_demuxer(s,DEMUXER_TYPE_OGG,0,-2,-2,NULL); + od = new_demuxer(opts, s,DEMUXER_TYPE_OGG,0,-2,-2,NULL); /// Add the header packets in the ogg demuxer audio stream for (i = 0; i < 3; i++) { diff --git a/libmpdemux/demux_pva.c b/libmpdemux/demux_pva.c index 2ff8be63e3..af16f1c3da 100644 --- a/libmpdemux/demux_pva.c +++ b/libmpdemux/demux_pva.c @@ -62,7 +62,7 @@ typedef struct { -int pva_sync(demuxer_t * demuxer) +static int pva_sync(demuxer_t * demuxer) { uint8_t buffer[5]={0,0,0,0,0}; int count; diff --git a/libmpdemux/demux_rtp.cpp b/libmpdemux/demux_rtp.cpp index aaa525fc4c..fd6dffa0e3 100644 --- a/libmpdemux/demux_rtp.cpp +++ b/libmpdemux/demux_rtp.cpp @@ -8,6 +8,7 @@ extern "C" { #endif #include "demux_rtp.h" #include "stheader.h" +#include "options.h" } #include "demux_rtp_internal.h" @@ -95,8 +96,8 @@ static char* openURL_sip(SIPClient* client, char const* url) { int rtspStreamOverTCP = 0; extern int rtsp_port; -extern "C" int audio_id, video_id, dvdsub_id; extern "C" demuxer_t* demux_open_rtp(demuxer_t* demuxer) { + struct MPOpts *opts = demuxer->opts; Boolean success = False; do { TaskScheduler* scheduler = BasicTaskScheduler::createNew(); @@ -256,8 +257,9 @@ extern "C" demuxer_t* demux_open_rtp(demuxer_t* demuxer) { // code to recognize this: if (demux_is_multiplexed_rtp_stream(demuxer)) { stream_t* s = new_ds_stream(demuxer->video); - demuxer_t* od = demux_open(s, DEMUXER_TYPE_UNKNOWN, - audio_id, video_id, dvdsub_id, NULL); + demuxer_t* od = demux_open(opts, s, DEMUXER_TYPE_UNKNOWN, + opts->audio_id, opts->video_id, opts->sub_id, + NULL); demuxer = new_demuxers_demuxer(od, od, od); } @@ -637,7 +639,7 @@ demux_packet_t* ReadBufferQueue::getPendingBuffer() { return dp; } -static int demux_rtp_control(struct demuxer_st *demuxer, int cmd, void *arg) { +static int demux_rtp_control(struct demuxer *demuxer, int cmd, void *arg) { double endpts = ((RTPState*)demuxer->priv)->mediaSession->playEndTime(); switch(cmd) { diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c index e360572d7f..f84c3d8b87 100644 --- a/libmpdemux/demuxer.c +++ b/libmpdemux/demuxer.c @@ -9,6 +9,8 @@ #include <sys/stat.h> #include "config.h" +#include "options.h" +#include "talloc.h" #include "mp_msg.h" #include "help_mp.h" #include "m_config.h" @@ -166,7 +168,7 @@ void free_demuxer_stream(demux_stream_t *ds) free(ds); } -demux_stream_t *new_demuxer_stream(struct demuxer_st *demuxer, int id) +demux_stream_t *new_demuxer_stream(struct demuxer *demuxer, int id) { demux_stream_t *ds = malloc(sizeof(demux_stream_t)); ds->buffer_pos = ds->buffer_size = 0; @@ -212,11 +214,10 @@ static const demuxer_desc_t *get_demuxer_desc_from_type(int file_format) } -demuxer_t *new_demuxer(stream_t *stream, int type, int a_id, int v_id, - int s_id, char *filename) +demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type, + int a_id, int v_id, int s_id, char *filename) { - demuxer_t *d = malloc(sizeof(demuxer_t)); - memset(d, 0, sizeof(demuxer_t)); + struct demuxer *d = talloc_zero(NULL, struct demuxer); d->stream = stream; d->stream_pts = MP_NOPTS_VALUE; d->reference_clock = MP_NOPTS_VALUE; @@ -229,6 +230,7 @@ demuxer_t *new_demuxer(stream_t *stream, int type, int a_id, int v_id, d->video = new_demuxer_stream(d, v_id); d->sub = new_demuxer_stream(d, s_id); d->type = type; + d->opts = opts; if (type) if (!(d->desc = get_demuxer_desc_from_type(type))) mp_msg(MSGT_DEMUXER, MSGL_ERR, @@ -241,8 +243,6 @@ demuxer_t *new_demuxer(stream_t *stream, int type, int a_id, int v_id, return d; } -extern int dvdsub_id; - sh_sub_t *new_sh_sub_sid(demuxer_t *demuxer, int id, int sid) { if (id > MAX_S_STREAMS - 1 || id < 0) { @@ -257,16 +257,17 @@ sh_sub_t *new_sh_sub_sid(demuxer_t *demuxer, int id, int sid) sh_sub_t *sh = calloc(1, sizeof(sh_sub_t)); demuxer->s_streams[id] = sh; sh->sid = sid; + sh->opts = demuxer->opts; mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SUBTITLE_ID=%d\n", sid); } - if (sid == dvdsub_id) { + if (sid == demuxer->opts->sub_id) { demuxer->sub->id = id; demuxer->sub->sh = demuxer->s_streams[id]; } return demuxer->s_streams[id]; } -void free_sh_sub(sh_sub_t *sh) +static void free_sh_sub(sh_sub_t *sh) { mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing sh_sub at %p\n", sh); free(sh->extradata); @@ -286,11 +287,11 @@ sh_audio_t *new_sh_audio_aid(demuxer_t *demuxer, int id, int aid) MAX_A_STREAMS); return NULL; } - if (demuxer->a_streams[id]) + if (demuxer->a_streams[id]) { mp_msg(MSGT_DEMUXER, MSGL_WARN, MSGTR_AudioStreamRedefined, id); - else { - sh_audio_t *sh = calloc(1, sizeof(sh_audio_t)); + } else { mp_msg(MSGT_DEMUXER, MSGL_V, MSGTR_FoundAudioStream, id); + sh_audio_t *sh = calloc(1, sizeof(sh_audio_t)); demuxer->a_streams[id] = sh; sh->aid = aid; sh->ds = demuxer->audio; @@ -299,6 +300,7 @@ sh_audio_t *new_sh_audio_aid(demuxer_t *demuxer, int id, int aid) sh->sample_format = AF_FORMAT_S16_NE; sh->audio_out_minsize = 8192; /* default size, maybe not enough for Win32/ACM */ sh->pts = MP_NOPTS_VALUE; + sh->opts = demuxer->opts; mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_ID=%d\n", aid); } return demuxer->a_streams[id]; @@ -326,11 +328,12 @@ sh_video_t *new_sh_video_vid(demuxer_t *demuxer, int id, int vid) if (demuxer->v_streams[id]) mp_msg(MSGT_DEMUXER, MSGL_WARN, MSGTR_VideoStreamRedefined, id); else { - sh_video_t *sh = calloc(1, sizeof(sh_video_t)); mp_msg(MSGT_DEMUXER, MSGL_V, MSGTR_FoundVideoStream, id); + sh_video_t *sh = calloc(1, sizeof *sh); demuxer->v_streams[id] = sh; sh->vid = vid; sh->ds = demuxer->video; + sh->opts = demuxer->opts; mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_ID=%d\n", vid); } return demuxer->v_streams[id]; @@ -387,7 +390,7 @@ void free_demuxer(demuxer_t *demuxer) } free(demuxer->attachments); } - free(demuxer); + talloc_free(demuxer); } @@ -492,6 +495,14 @@ int ds_fill_buffer(demux_stream_t *ds) if (!ds->first) ds->last = NULL; --ds->packs; + /* The code below can set ds->eof to 1 when another stream runs + * out of buffer space. That makes sense because in that situation + * the calling code should not count on being able to demux more + * packets from this stream. + * If however the situation improves and we're called again + * despite the eof flag then it's better to clear it to avoid + * weird behavior. */ + ds->eof = 0; return 1; } if (demux->audio->packs >= MAX_PACKS @@ -747,9 +758,6 @@ int get_demuxer_type_from_name(char *demuxer_name, int *force) int extension_parsing = 1; // 0=off 1=mixed (used only for unstable formats) -int correct_pts = 0; -int user_correct_pts = -1; - /* NOTE : Several demuxers may be opened at the same time so demuxers should NEVER rely on an external var to enable them @@ -763,9 +771,10 @@ int user_correct_pts = -1; (ex: tv,mf). */ -static demuxer_t *demux_open_stream(stream_t *stream, int file_format, - int force, int audio_id, int video_id, - int dvdsub_id, char *filename) +static demuxer_t *demux_open_stream(struct MPOpts *opts, stream_t *stream, + int file_format, int force, int audio_id, + int video_id, int dvdsub_id, + char *filename) { demuxer_t *demuxer = NULL; @@ -778,7 +787,7 @@ static demuxer_t *demux_open_stream(stream_t *stream, int file_format, // If somebody requested a demuxer check it if (file_format) { if ((demuxer_desc = get_demuxer_desc_from_type(file_format))) { - demuxer = new_demuxer(stream, demuxer_desc->type, audio_id, + demuxer = new_demuxer(opts, stream, demuxer_desc->type, audio_id, video_id, dvdsub_id, filename); if (demuxer_desc->check_file) fformat = demuxer_desc->check_file(demuxer); @@ -800,8 +809,9 @@ static demuxer_t *demux_open_stream(stream_t *stream, int file_format, } else { // Format changed after check, recurse free_demuxer(demuxer); - return demux_open_stream(stream, fformat, force, audio_id, - video_id, dvdsub_id, filename); + return demux_open_stream(opts, stream, fformat, force, + audio_id, video_id, dvdsub_id, + filename); } } // Check failed for forced demuxer, quit @@ -812,7 +822,7 @@ static demuxer_t *demux_open_stream(stream_t *stream, int file_format, // Test demuxers with safe file checks for (i = 0; (demuxer_desc = demuxer_list[i]); i++) { if (demuxer_desc->safe_check) { - demuxer = new_demuxer(stream, demuxer_desc->type, audio_id, + demuxer = new_demuxer(opts, stream, demuxer_desc->type, audio_id, video_id, dvdsub_id, filename); if ((fformat = demuxer_desc->check_file(demuxer)) != 0) { if (fformat == demuxer_desc->type) { @@ -831,7 +841,7 @@ static demuxer_t *demux_open_stream(stream_t *stream, int file_format, return demuxer; // handled in mplayer.c // Format changed after check, recurse free_demuxer(demuxer); - demuxer = demux_open_stream(stream, fformat, force, + demuxer = demux_open_stream(opts, stream, fformat, force, audio_id, video_id, dvdsub_id, filename); if (demuxer) @@ -853,8 +863,9 @@ static demuxer_t *demux_open_stream(stream_t *stream, int file_format, file_format = demuxer_type_by_filename(filename); if (file_format != DEMUXER_TYPE_UNKNOWN) { // we like recursion :) - demuxer = demux_open_stream(stream, file_format, force, audio_id, - video_id, dvdsub_id, filename); + demuxer = demux_open_stream(opts, stream, file_format, force, + audio_id, video_id, dvdsub_id, + filename); if (demuxer) return demuxer; // done! file_format = DEMUXER_TYPE_UNKNOWN; // continue fuzzy guessing... @@ -865,7 +876,7 @@ static demuxer_t *demux_open_stream(stream_t *stream, int file_format, // Try detection for all other demuxers for (i = 0; (demuxer_desc = demuxer_list[i]); i++) { if (!demuxer_desc->safe_check && demuxer_desc->check_file) { - demuxer = new_demuxer(stream, demuxer_desc->type, audio_id, + demuxer = new_demuxer(opts, stream, demuxer_desc->type, audio_id, video_id, dvdsub_id, filename); if ((fformat = demuxer_desc->check_file(demuxer)) != 0) { if (fformat == demuxer_desc->type) { @@ -884,7 +895,7 @@ static demuxer_t *demux_open_stream(stream_t *stream, int file_format, return demuxer; // handled in mplayer.c // Format changed after check, recurse free_demuxer(demuxer); - demuxer = demux_open_stream(stream, fformat, force, + demuxer = demux_open_stream(opts, stream, fformat, force, audio_id, video_id, dvdsub_id, filename); if (demuxer) @@ -942,8 +953,9 @@ extern int hr_mp3_seek; extern float stream_cache_min_percent; extern float stream_cache_seek_min_percent; -demuxer_t *demux_open(stream_t *vs, int file_format, int audio_id, - int video_id, int dvdsub_id, char *filename) +demuxer_t *demux_open(struct MPOpts *opts, stream_t *vs, int file_format, + int audio_id, int video_id, int dvdsub_id, + char *filename) { stream_t *as = NULL, *ss = NULL; demuxer_t *vd, *ad = NULL, *sd = NULL; @@ -1001,7 +1013,7 @@ demuxer_t *demux_open(stream_t *vs, int file_format, int audio_id, } } - vd = demux_open_stream(vs, demuxer_type ? demuxer_type : file_format, + vd = demux_open_stream(opts, vs, demuxer_type ? demuxer_type : file_format, demuxer_force, audio_stream ? -2 : audio_id, video_id, sub_stream ? -2 : dvdsub_id, filename); if (!vd) { @@ -1012,7 +1024,7 @@ demuxer_t *demux_open(stream_t *vs, int file_format, int audio_id, return NULL; } if (as) { - ad = demux_open_stream(as, + ad = demux_open_stream(opts, as, audio_demuxer_type ? audio_demuxer_type : afmt, audio_demuxer_force, audio_id, -2, -2, audio_stream); @@ -1025,7 +1037,8 @@ demuxer_t *demux_open(stream_t *vs, int file_format, int audio_id, hr_mp3_seek = 1; // Enable high res seeking } if (ss) { - sd = demux_open_stream(ss, sub_demuxer_type ? sub_demuxer_type : sfmt, + sd = demux_open_stream(opts, ss, + sub_demuxer_type ? sub_demuxer_type : sfmt, sub_demuxer_force, -2, -2, dvdsub_id, sub_stream); if (!sd) { @@ -1044,10 +1057,11 @@ demuxer_t *demux_open(stream_t *vs, int file_format, int audio_id, else res = vd; - correct_pts = user_correct_pts; - if (correct_pts < 0) - correct_pts = demux_control(res, DEMUXER_CTRL_CORRECT_PTS, NULL) - == DEMUXER_CTRL_OK; + opts->correct_pts = opts->user_correct_pts; + if (opts->correct_pts < 0) + opts->correct_pts = + demux_control(res, DEMUXER_CTRL_CORRECT_PTS, + NULL) == DEMUXER_CTRL_OK; return res; } @@ -1080,9 +1094,8 @@ int demux_seek(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, mp_msg(MSGT_SEEK, MSGL_WARN, MSGTR_CantSeekFile); return 0; } - - demux_flush(demuxer); // clear demux buffers: + demux_flush(demuxer); if (sh_audio) sh_audio->a_buffer_len = 0; @@ -1141,8 +1154,8 @@ int demux_info_add(demuxer_t *demuxer, const char *opt, const char *param) } } - info = demuxer->info = (char **) realloc(info, - (2 * (n + 2)) * sizeof(char *)); + info = demuxer->info = + (char **) realloc(info, (2 * (n + 2)) * sizeof(char *)); info[2 * n] = strdup(opt); info[2 * n + 1] = strdup(param); memset(&info[2 * (n + 1)], 0, 2 * sizeof(char *)); @@ -1318,31 +1331,19 @@ int demuxer_add_chapter(demuxer_t *demuxer, const char *name, uint64_t start, * either using the demuxer->chapters structure set by the demuxer * or asking help to the stream layer (e.g. dvd) * \param chapter - chapter number wished - 0-based - * \param mode 0: relative to current main pts, 1: absolute * \param seek_pts set by the function to the pts to seek to (if demuxer->chapters is set) - * \param num_chapters number of chapters present (set by this function is param is not null) * \param chapter_name name of chapter found (set by this function is param is not null) * \return -1 on error, current chapter if successful */ -int demuxer_seek_chapter(demuxer_t *demuxer, int chapter, int mode, - float *seek_pts, int *num_chapters, +int demuxer_seek_chapter(demuxer_t *demuxer, int chapter, double *seek_pts, char **chapter_name) { int ris; - int current, total; sh_video_t *sh_video = demuxer->video->sh; sh_audio_t *sh_audio = demuxer->audio->sh; if (!demuxer->num_chapters || !demuxer->chapters) { - if (!mode) { - ris = stream_control(demuxer->stream, - STREAM_CTRL_GET_CURRENT_CHAPTER, ¤t); - if (ris == STREAM_UNSUPPORTED) - return -1; - chapter += current; - } - demux_flush(demuxer); ris = stream_control(demuxer->stream, STREAM_CTRL_SEEK_TO_CHAPTER, @@ -1362,60 +1363,31 @@ int demuxer_seek_chapter(demuxer_t *demuxer, int chapter, int mode, // (because e.g. dvds depend on sectors, not on pts) *seek_pts = -1.0; - if (num_chapters) { - if (stream_control(demuxer->stream, STREAM_CTRL_GET_NUM_CHAPTERS, - num_chapters) == STREAM_UNSUPPORTED) - *num_chapters = 0; - } - if (chapter_name) { *chapter_name = NULL; - if (num_chapters && *num_chapters) { - char *tmp = malloc(16); - if (tmp) { - sprintf(tmp, " of %3d", *num_chapters); - *chapter_name = tmp; - } + int num_chapters; + if (stream_control(demuxer->stream, STREAM_CTRL_GET_NUM_CHAPTERS, + &num_chapters) == STREAM_UNSUPPORTED) + num_chapters = 0; + if (num_chapters) { + *chapter_name = talloc_size(NULL, 16); + sprintf(*chapter_name, " of %3d", num_chapters); } } return ris != STREAM_UNSUPPORTED ? chapter : -1; } else { // chapters structure is set in the demuxer - total = demuxer->num_chapters; - - if (mode == 1) //absolute seeking - current = chapter; - else { //relative seeking - uint64_t now; - now = (sh_video ? sh_video->pts : (sh_audio ? sh_audio->pts : 0.)) - * 1000 + .5; - - for (current = total - 1; current >= 0; --current) { - demux_chapter_t *chapter = demuxer->chapters + current; - if (chapter->start <= now) - break; - } - current += chapter; - } - - if (current >= total) + if (chapter >= demuxer->num_chapters) return -1; - if (current < 0) - current = 0; - - *seek_pts = demuxer->chapters[current].start / 1000.0; + if (chapter < 0) + chapter = 0; - if (num_chapters) - *num_chapters = demuxer->num_chapters; + *seek_pts = demuxer->chapters[chapter].start / 1000.0; - if (chapter_name) { - if (demuxer->chapters[current].name) - *chapter_name = strdup(demuxer->chapters[current].name); - else - *chapter_name = NULL; - } + if (chapter_name) + *chapter_name = talloc_strdup(NULL, demuxer->chapters[chapter].name); - return current; + return chapter; } } diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h index 6a1e26dd02..544afe8add 100644 --- a/libmpdemux/demuxer.h +++ b/libmpdemux/demuxer.h @@ -5,11 +5,11 @@ #include <stdint.h> #include <stdlib.h> #include <string.h> +#include <stdbool.h> #include "stream/stream.h" -#ifdef CONFIG_ASS -#include "libass/ass_types.h" -#endif + +struct MPOpts; #ifdef HAVE_BUILTIN_EXPECT #define likely(x) __builtin_expect ((x) != 0, 1) @@ -20,7 +20,7 @@ #endif #define MAX_PACKS 4096 -#define MAX_PACK_BYTES 0x2000000 +#define MAX_PACK_BYTES 0x8000000 // 128 MiB #define DEMUXER_TYPE_UNKNOWN 0 #define DEMUXER_TYPE_MPEG_ES 1 @@ -96,11 +96,13 @@ #define SEEK_ABSOLUTE (1 << 0) #define SEEK_FACTOR (1 << 1) +#define SEEK_FORWARD (1 << 2) +#define SEEK_BACKWARD (1 << 3) #define MP_INPUT_BUFFER_PADDING_SIZE 8 // Holds one packet/frame/whatever -typedef struct demux_packet_st { +typedef struct demux_packet { int len; double pts; double endpts; @@ -109,11 +111,11 @@ typedef struct demux_packet_st { unsigned char* buffer; int flags; // keyframe, etc int refcount; //refcounter for the master packet, if 0, buffer can be free()d - struct demux_packet_st* master; //pointer to the master packet if this one is a cloned one - struct demux_packet_st* next; + struct demux_packet *master; //pointer to the master packet if this one is a cloned one + struct demux_packet *next; } demux_packet_t; -typedef struct { +typedef struct demux_stream { int buffer_pos; // current buffer position int buffer_size; // current buffer size unsigned char* buffer; // current buffer, never free() it, always use free_demux_packet(buffer_ref); @@ -131,7 +133,7 @@ typedef struct { demux_packet_t *last; // append new packets from input stream to here demux_packet_t *current;// needed for refcounting of the buffer int id; // stream ID (for multiple audio/video streams) - struct demuxer_st *demuxer; // parent demuxer structure (stream handler) + struct demuxer *demuxer; // parent demuxer structure (stream handler) // ---- asf ----- demux_packet_t *asf_packet; // read asf fragments here int asf_seq; @@ -141,7 +143,7 @@ typedef struct { void* sh; } demux_stream_t; -typedef struct demuxer_info_st { +typedef struct demuxer_info { char *name; char *author; char *encoder; @@ -153,15 +155,12 @@ typedef struct demuxer_info_st { #define MAX_V_STREAMS 256 #define MAX_S_STREAMS 256 -struct demuxer_st; - -extern int correct_pts; -extern int user_correct_pts; +struct demuxer; /** * Demuxer description structure */ -typedef struct demuxers_desc_st { +typedef struct demuxer_desc { const char *info; ///< What is it (long name and/or description) const char *name; ///< Demuxer name, used with -demuxer switch const char *shortdesc; ///< Description printed at demuxer detection @@ -172,26 +171,39 @@ typedef struct demuxers_desc_st { int safe_check; ///< If 1 detection is safe and fast, do it before file extension check /// Check if can demux the file, return DEMUXER_TYPE_xxx on success - int (*check_file)(struct demuxer_st *demuxer); ///< Mandatory if safe_check == 1, else optional + int (*check_file)(struct demuxer *demuxer); ///< Mandatory if safe_check == 1, else optional /// Get packets from file, return 0 on eof - int (*fill_buffer)(struct demuxer_st *demuxer, demux_stream_t *ds); ///< Mandatory + int (*fill_buffer)(struct demuxer *demuxer, demux_stream_t *ds); ///< Mandatory /// Open the demuxer, return demuxer on success, NULL on failure - struct demuxer_st* (*open)(struct demuxer_st *demuxer); ///< Optional + struct demuxer* (*open)(struct demuxer *demuxer); ///< Optional /// Close the demuxer - void (*close)(struct demuxer_st *demuxer); ///< Optional + void (*close)(struct demuxer *demuxer); ///< Optional // Seek - void (*seek)(struct demuxer_st *demuxer, float rel_seek_secs, float audio_delay, int flags); ///< Optional + void (*seek)(struct demuxer *demuxer, float rel_seek_secs, float audio_delay, int flags); ///< Optional // Control - int (*control)(struct demuxer_st *demuxer, int cmd, void *arg); ///< Optional + int (*control)(struct demuxer *demuxer, int cmd, void *arg); ///< Optional } demuxer_desc_t; -typedef struct demux_chapter_s +typedef struct demux_chapter { uint64_t start, end; char* name; } demux_chapter_t; -typedef struct demux_attachment_s +struct matroska_data { + unsigned char segment_uid[16]; + // Ordered chapter information if any + struct matroska_chapter { + uint64_t start; + uint64_t end; + bool has_segment_uid; + unsigned char segment_uid[16]; + char *name; + } *ordered_chapters; + int num_ordered_chapters; +}; + +typedef struct demux_attachment { char* name; char* type; @@ -199,7 +211,7 @@ typedef struct demux_attachment_s unsigned int data_size; } demux_attachment_t; -typedef struct demuxer_st { +typedef struct demuxer { const demuxer_desc_t *desc; ///< Demuxer description structure off_t filepos; // input stream current pos. off_t movi_start; @@ -212,24 +224,30 @@ typedef struct demuxer_st { int type; // demuxer type: mpeg PS, mpeg ES, avi, avi-ni, avi-nini, asf int file_format; // file format: mpeg/avi/asf int seekable; // flag + /* Set if using absolute seeks for small movements is OK (no pts resets + * that would make pts ambigious, preferably supports back/forward flags */ + bool accurate_seek; // demux_stream_t *audio; // audio buffer/demuxer demux_stream_t *video; // video buffer/demuxer demux_stream_t *sub; // dvd subtitle buffer/demuxer // stream headers: - void* a_streams[MAX_A_STREAMS]; // audio streams (sh_audio_t) - void* v_streams[MAX_V_STREAMS]; // video sterams (sh_video_t) - void *s_streams[MAX_S_STREAMS]; // dvd subtitles (flag) + struct sh_audio *a_streams[MAX_A_STREAMS]; + struct sh_video *v_streams[MAX_V_STREAMS]; + struct sh_sub *s_streams[MAX_S_STREAMS]; demux_chapter_t* chapters; int num_chapters; - + demux_attachment_t* attachments; int num_attachments; + struct matroska_data matroska_data; + void* priv; // fileformat-dependent data char** info; + struct MPOpts *opts; } demuxer_t; typedef struct { @@ -311,8 +329,8 @@ static inline void *realloc_struct(void *ptr, size_t nmemb, size_t size) { return realloc(ptr, nmemb * size); } -demux_stream_t* new_demuxer_stream(struct demuxer_st *demuxer,int id); -demuxer_t* new_demuxer(stream_t *stream,int type,int a_id,int v_id,int s_id,char *filename); +demux_stream_t* new_demuxer_stream(struct demuxer *demuxer,int id); +demuxer_t* new_demuxer(struct MPOpts *opts, stream_t *stream,int type,int a_id,int v_id,int s_id,char *filename); void free_demuxer_stream(demux_stream_t *ds); void free_demuxer(demuxer_t *demuxer); @@ -375,7 +393,7 @@ static inline int avi_stream_id(unsigned int id){ return a*10+b; } -demuxer_t* demux_open(stream_t *stream,int file_format,int aid,int vid,int sid,char* filename); +demuxer_t* demux_open(struct MPOpts *opts, stream_t *stream,int file_format,int aid,int vid,int sid,char* filename); void demux_flush(demuxer_t *demuxer); int demux_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags); demuxer_t* new_demuxers_demuxer(demuxer_t* vd, demuxer_t* ad, demuxer_t* sd); @@ -414,7 +432,8 @@ int demuxer_add_attachment(demuxer_t* demuxer, const char* name, const char* type, const void* data, size_t size); int demuxer_add_chapter(demuxer_t* demuxer, const char* name, uint64_t start, uint64_t end); -int demuxer_seek_chapter(demuxer_t *demuxer, int chapter, int mode, float *seek_pts, int *num_chapters, char **chapter_name); +int demuxer_seek_chapter(demuxer_t *demuxer, int chapter, double *seek_pts, + char **chapter_name); /// Get current chapter index if available. int demuxer_get_current_chapter(demuxer_t *demuxer); diff --git a/libmpdemux/ebml.h b/libmpdemux/ebml.h index c4d7256d91..345f08b46a 100644 --- a/libmpdemux/ebml.h +++ b/libmpdemux/ebml.h @@ -54,6 +54,7 @@ #define MATROSKA_ID_WRITINGAPP 0x5741 #define MATROSKA_ID_MUXINGAPP 0x4D80 #define MATROSKA_ID_DATEUTC 0x4461 +#define MATROSKA_ID_SEGMENTUID 0x73A4 /* ID in the tracks master */ #define MATROSKA_ID_TRACKENTRY 0xAE @@ -126,11 +127,13 @@ /* IDs in the chapters master */ #define MATROSKA_ID_EDITIONENTRY 0x45B9 +#define MATROSKA_ID_EDITIONFLAGORDERED 0x45DD #define MATROSKA_ID_CHAPTERATOM 0xB6 #define MATROSKA_ID_CHAPTERTIMESTART 0x91 #define MATROSKA_ID_CHAPTERTIMEEND 0x92 #define MATROSKA_ID_CHAPTERDISPLAY 0x80 #define MATROSKA_ID_CHAPSTRING 0x85 +#define MATROSKA_ID_CHAPTERSEGMENTUID 0x6E67 /* IDs in the cluster master */ #define MATROSKA_ID_CLUSTERTIMECODE 0xE7 diff --git a/libmpdemux/mp3_hdr.c b/libmpdemux/mp3_hdr.c index cb59878466..da1826215c 100644 --- a/libmpdemux/mp3_hdr.c +++ b/libmpdemux/mp3_hdr.c @@ -1,6 +1,7 @@ #include <stdio.h> #include "config.h" +#include "mp3_hdr.h" #include "mp_msg.h" //----------------------- mp3 audio frame header parser ----------------------- @@ -19,7 +20,7 @@ static long freqs[9] = { 44100, 48000, 32000, // MPEG 1.0 22050, 24000, 16000, // MPEG 2.0 11025, 12000, 8000}; // MPEG 2.5 -int mp_mp3_get_lsf(unsigned char* hbuf){ +static int mp_mp3_get_lsf(unsigned char* hbuf){ unsigned long newhead = hbuf[0] << 24 | hbuf[1] << 16 | diff --git a/libmpdemux/parse_mp4.c b/libmpdemux/parse_mp4.c index f2a39abe6e..c9f9ff2e80 100644 --- a/libmpdemux/parse_mp4.c +++ b/libmpdemux/parse_mp4.c @@ -33,7 +33,7 @@ #define MP4_DL MSGL_V #define freereturn(a,b) free(a); return b -int mp4_read_descr_len(stream_t *s) { +static int mp4_read_descr_len(stream_t *s) { uint8_t b; uint8_t numBytes = 0; uint32_t length = 0; diff --git a/libmpdemux/stheader.h b/libmpdemux/stheader.h index 07ecfaeded..12a9144fc6 100644 --- a/libmpdemux/stheader.h +++ b/libmpdemux/stheader.h @@ -1,16 +1,18 @@ #ifndef MPLAYER_STHEADER_H #define MPLAYER_STHEADER_H -#include "demuxer.h" #include "aviheader.h" #include "ms_hdr.h" +struct MPOpts; +struct demuxer; // Stream headers: -typedef struct { +typedef struct sh_audio { + struct MPOpts *opts; int aid; - demux_stream_t *ds; - struct codecs_st *codec; + struct demux_stream *ds; + struct codecs *codec; unsigned int format; int initialized; float stream_delay; // number of seconds stream should be delayed (according to dwStart or similar) @@ -36,8 +38,8 @@ typedef struct { int a_out_buffer_len; int a_out_buffer_size; // void* audio_out; // the audio_out handle, used for this audio stream - struct af_stream_s *afilter; // the audio filter stream - struct ad_functions_s* ad_driver; + struct af_stream *afilter; // the audio filter stream + struct ad_functions *ad_driver; #ifdef CONFIG_DYNAMIC_PLUGINS void *dec_handle; #endif @@ -54,10 +56,11 @@ typedef struct { int default_track; } sh_audio_t; -typedef struct { +typedef struct sh_video { + struct MPOpts *opts; int vid; - demux_stream_t *ds; - struct codecs_st *codec; + struct demux_stream *ds; + struct codecs *codec; unsigned int format; int initialized; float timer; // absolute time in video stream, since last start/seek @@ -81,7 +84,9 @@ typedef struct { int disp_w,disp_h; // display size (filled by fileformat parser) // output driver/filters: (set by libmpcodecs core) unsigned int outfmtidx; - struct vf_instance_s *vfilter; // the video filter chain, used for this video stream + struct vf_instance *vfilter; // the video filter chain, used for this video stream + int output_flags; // query_format() results for output filters+vo + const struct vd_functions *vd_driver; int vf_initialized; #ifdef CONFIG_DYNAMIC_PLUGINS void *dec_handle; @@ -94,26 +99,25 @@ typedef struct { void* context; // codec-specific stuff (usually HANDLE or struct pointer) } sh_video_t; -typedef struct { +typedef struct sh_sub { + struct MPOpts *opts; int sid; char type; // t = text, v = VobSub, a = SSA/ASS unsigned char* extradata; // extra header data passed from demuxer int extradata_len; -#ifdef CONFIG_ASS - ass_track_t* ass_track; // for SSA/ASS streams (type == 'a') -#endif + struct ass_track_s *ass_track; // for SSA/ASS streams (type == 'a') char* lang; // track language int default_track; } sh_sub_t; // demuxer.c: #define new_sh_audio(d, i) new_sh_audio_aid(d, i, i) -sh_audio_t* new_sh_audio_aid(demuxer_t *demuxer,int id,int aid); +sh_audio_t* new_sh_audio_aid(struct demuxer *demuxer,int id,int aid); #define new_sh_video(d, i) new_sh_video_vid(d, i, i) -sh_video_t* new_sh_video_vid(demuxer_t *demuxer,int id,int vid); +sh_video_t* new_sh_video_vid(struct demuxer *demuxer,int id,int vid); #define new_sh_sub(d, i) new_sh_sub_sid(d, i, i) -sh_sub_t *new_sh_sub_sid(demuxer_t *demuxer, int id, int sid); -void free_sh_audio(demuxer_t *demuxer, int id); +sh_sub_t *new_sh_sub_sid(struct demuxer *demuxer, int id, int sid); +void free_sh_audio(struct demuxer *demuxer, int id); void free_sh_video(sh_video_t *sh); // video.c: |