summaryrefslogtreecommitdiffstats
path: root/libmpdemux/demuxer.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-11-05 17:02:04 +0100
committerwm4 <wm4@nowhere>2012-11-12 20:06:14 +0100
commitd4bdd0473d6f43132257c9fb3848d829755167a3 (patch)
tree8021c2f7da1841393c8c832105e20cd527826d6c /libmpdemux/demuxer.c
parentbd48deba77bd5582c5829d6fe73a7d2571088aba (diff)
downloadmpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.bz2
mpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.xz
Rename directories, move files (step 1 of 2) (does not compile)
Tis drops the silly lib prefixes, and attempts to organize the tree in a more logical way. Make the top-level directory less cluttered as well. Renames the following directories: libaf -> audio/filter libao2 -> audio/out libvo -> video/out libmpdemux -> demux Split libmpcodecs: vf* -> video/filter vd*, dec_video.* -> video/decode mp_image*, img_format*, ... -> video/ ad*, dec_audio.* -> audio/decode libaf/format.* is moved to audio/ - this is similar to how mp_image.* is located in video/. Move most top-level .c/.h files to core. (talloc.c/.h is left on top- level, because it's external.) Park some of the more annoying files in compat/. Some of these are relicts from the time mplayer used ffmpeg internals. sub/ is not split, because it's too much of a mess (subtitle code is mixed with OSD display and rendering). Maybe the organization of core is not ideal: it mixes playback core (like mplayer.c) and utility helpers (like bstr.c/h). Should the need arise, the playback core will be moved somewhere else, while core contains all helper and common code.
Diffstat (limited to 'libmpdemux/demuxer.c')
-rw-r--r--libmpdemux/demuxer.c1435
1 files changed, 0 insertions, 1435 deletions
diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c
deleted file mode 100644
index 3673fd06e3..0000000000
--- a/libmpdemux/demuxer.c
+++ /dev/null
@@ -1,1435 +0,0 @@
-/*
- * DEMUXER v2.5
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <unistd.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "config.h"
-#include "options.h"
-#include "talloc.h"
-#include "mp_msg.h"
-#include "m_config.h"
-
-#include "stream/stream.h"
-#include "demuxer.h"
-#include "stheader.h"
-#include "mf.h"
-
-#include "libaf/format.h"
-
-#include "libavcodec/avcodec.h"
-#if MP_INPUT_BUFFER_PADDING_SIZE < FF_INPUT_BUFFER_PADDING_SIZE
-#error MP_INPUT_BUFFER_PADDING_SIZE is too small!
-#endif
-
-static void clear_parser(sh_common_t *sh);
-
-// Demuxer list
-extern const struct demuxer_desc demuxer_desc_edl;
-extern const struct demuxer_desc demuxer_desc_cue;
-extern const demuxer_desc_t demuxer_desc_rawaudio;
-extern const demuxer_desc_t demuxer_desc_rawvideo;
-extern const demuxer_desc_t demuxer_desc_tv;
-extern const demuxer_desc_t demuxer_desc_mf;
-extern const demuxer_desc_t demuxer_desc_avi;
-extern const demuxer_desc_t demuxer_desc_asf;
-extern const demuxer_desc_t demuxer_desc_matroska;
-extern const demuxer_desc_t demuxer_desc_gif;
-extern const demuxer_desc_t demuxer_desc_lavf;
-extern const demuxer_desc_t demuxer_desc_lavf_preferred;
-extern const demuxer_desc_t demuxer_desc_mng;
-extern const demuxer_desc_t demuxer_desc_mpeg_ps;
-extern const demuxer_desc_t demuxer_desc_mpeg_pes;
-extern const demuxer_desc_t demuxer_desc_mpeg_gxf;
-extern const demuxer_desc_t demuxer_desc_mpeg_es;
-extern const demuxer_desc_t demuxer_desc_mpeg4_es;
-extern const demuxer_desc_t demuxer_desc_h264_es;
-extern const demuxer_desc_t demuxer_desc_mpeg_ts;
-
-/* Please do not add any new demuxers here. If you want to implement a new
- * demuxer, add it to libavformat, except for wrappers around external
- * libraries and demuxers requiring binary support. */
-
-const demuxer_desc_t *const demuxer_list[] = {
- &demuxer_desc_edl,
- &demuxer_desc_cue,
- &demuxer_desc_rawaudio,
- &demuxer_desc_rawvideo,
-#ifdef CONFIG_TV
- &demuxer_desc_tv,
-#endif
- &demuxer_desc_mf,
- &demuxer_desc_lavf_preferred,
- &demuxer_desc_avi,
- &demuxer_desc_asf,
- &demuxer_desc_matroska,
-#ifdef CONFIG_GIF
- &demuxer_desc_gif,
-#endif
- &demuxer_desc_lavf,
-#ifdef CONFIG_MNG
- &demuxer_desc_mng,
-#endif
- &demuxer_desc_mpeg_ps,
- &demuxer_desc_mpeg_pes,
- &demuxer_desc_mpeg_gxf,
- &demuxer_desc_mpeg_es,
- &demuxer_desc_mpeg4_es,
- &demuxer_desc_h264_es,
- &demuxer_desc_mpeg_ts,
- /* Please do not add any new demuxers here. If you want to implement a new
- * demuxer, add it to libavformat, except for wrappers around external
- * libraries and demuxers requiring binary support. */
- NULL
-};
-
-static struct demux_packet *create_packet(size_t len)
-{
- if (len > 1000000000) {
- mp_msg(MSGT_DEMUXER, MSGL_FATAL, "Attempt to allocate demux packet "
- "over 1 GB!\n");
- abort();
- }
- struct demux_packet *dp = malloc(sizeof(struct demux_packet));
- dp->len = len;
- dp->next = NULL;
- dp->pts = MP_NOPTS_VALUE;
- dp->duration = -1;
- dp->stream_pts = MP_NOPTS_VALUE;
- dp->pos = 0;
- dp->keyframe = false;
- dp->refcount = 1;
- dp->master = NULL;
- dp->buffer = NULL;
- dp->avpacket = NULL;
- return dp;
-}
-
-struct demux_packet *new_demux_packet(size_t len)
-{
- struct demux_packet *dp = create_packet(len);
- dp->buffer = malloc(len + MP_INPUT_BUFFER_PADDING_SIZE);
- if (!dp->buffer) {
- mp_msg(MSGT_DEMUXER, MSGL_FATAL, "Memory allocation failure!\n");
- abort();
- }
- memset(dp->buffer + len, 0, 8);
- return dp;
-}
-
-// data must already have suitable padding
-struct demux_packet *new_demux_packet_fromdata(void *data, size_t len)
-{
- struct demux_packet *dp = create_packet(len);
- dp->buffer = data;
- return dp;
-}
-
-void resize_demux_packet(struct demux_packet *dp, size_t len)
-{
- if (len > 1000000000) {
- mp_msg(MSGT_DEMUXER, MSGL_FATAL, "Attempt to realloc demux packet "
- "over 1 GB!\n");
- abort();
- }
- dp->buffer = realloc(dp->buffer, len + MP_INPUT_BUFFER_PADDING_SIZE);
- if (!dp->buffer) {
- mp_msg(MSGT_DEMUXER, MSGL_FATAL, "Memory allocation failure!\n");
- abort();
- }
- memset(dp->buffer + len, 0, 8);
- dp->len = len;
-}
-
-struct demux_packet *clone_demux_packet(struct demux_packet *pack)
-{
- struct demux_packet *dp = malloc(sizeof(struct demux_packet));
- while (pack->master)
- pack = pack->master; // find the master
- memcpy(dp, pack, sizeof(struct demux_packet));
- dp->next = NULL;
- dp->refcount = 0;
- dp->master = pack;
- pack->refcount++;
- return dp;
-}
-
-void free_demux_packet(struct demux_packet *dp)
-{
- if (dp->master == NULL) { //dp is a master packet
- dp->refcount--;
- if (dp->refcount == 0) {
- if (dp->avpacket)
- talloc_free(dp->avpacket);
- else
- free(dp->buffer);
- free(dp);
- }
- return;
- }
- // dp is a clone:
- free_demux_packet(dp->master);
- free(dp);
-}
-
-static void free_demuxer_stream(struct demux_stream *ds)
-{
- ds_free_packs(ds);
- free(ds);
-}
-
-static struct demux_stream *new_demuxer_stream(struct demuxer *demuxer,
- enum stream_type type, int id)
-{
- demux_stream_t *ds = malloc(sizeof(demux_stream_t));
- *ds = (demux_stream_t) {
- .stream_type = type,
- .id = id,
- .demuxer = demuxer,
- .asf_seq = -1,
- };
- return ds;
-}
-
-struct sh_stream *ds_gsh(struct demux_stream *ds)
-{
- // Ideally ds would have a gsh field, but since all the old demuxers set
- // ds->sh themselves and we don't want to change them, enjoy this hack.
- if (!ds->sh)
- return NULL;
- switch (ds->stream_type) {
- case STREAM_VIDEO: return ((struct sh_video *)ds->sh)->gsh;
- case STREAM_AUDIO: return ((struct sh_audio *)ds->sh)->gsh;
- case STREAM_SUB: return ((struct sh_sub *)ds->sh)->gsh;
- }
- assert(false);
-}
-
-/**
- * Get demuxer description structure for a given demuxer type
- *
- * @param file_format type of the demuxer
- * @return structure for the demuxer, NULL if not found
- */
-static const demuxer_desc_t *get_demuxer_desc_from_type(int file_format)
-{
- int i;
-
- for (i = 0; demuxer_list[i]; i++)
- if (file_format == demuxer_list[i]->type)
- return demuxer_list[i];
-
- return NULL;
-}
-
-
-demuxer_t *new_demuxer(struct MPOpts *opts, stream_t *stream, int type,
- int a_id, int v_id, int s_id, char *filename)
-{
- struct demuxer *d = talloc_zero(NULL, struct demuxer);
- d->stream = stream;
- d->stream_pts = MP_NOPTS_VALUE;
- d->reference_clock = MP_NOPTS_VALUE;
- d->movi_start = stream->start_pos;
- d->movi_end = stream->end_pos;
- d->seekable = 1;
- d->synced = 0;
- d->filepos = -1;
- d->audio = new_demuxer_stream(d, STREAM_VIDEO, a_id);
- d->video = new_demuxer_stream(d, STREAM_AUDIO, v_id);
- d->sub = new_demuxer_stream(d, STREAM_SUB, s_id);
- d->ds[STREAM_VIDEO] = d->video;
- d->ds[STREAM_AUDIO] = d->audio;
- d->ds[STREAM_SUB] = d->sub;
- d->type = type;
- d->opts = opts;
- if (type)
- if (!(d->desc = get_demuxer_desc_from_type(type)))
- mp_msg(MSGT_DEMUXER, MSGL_ERR,
- "BUG! Invalid demuxer type in new_demuxer(), "
- "big troubles ahead.\n");
- if (filename) // Filename hack for avs_check_file
- d->filename = strdup(filename);
- stream_seek(stream, stream->start_pos);
- return d;
-}
-
-const char *sh_sub_type2str(int type)
-{
- switch (type) {
- case 't': return "text";
- case 'm': return "movtext";
- case 'a': return "ass";
- case 'v': return "vobsub";
- case 'x': return "xsub";
- case 'b': return "dvb";
- case 'd': return "dvb-teletext";
- case 'p': return "hdmv pgs";
- }
- return "unknown";
-}
-
-static struct sh_stream *new_sh_stream(demuxer_t *demuxer,
- enum stream_type type,
- int stream_index,
- int tid)
-{
- struct sh_stream *sh = talloc_struct(demuxer, struct sh_stream, {
- .type = type,
- .demuxer = demuxer,
- .index = demuxer->num_streams,
- .demuxer_id = tid, // may be overwritten by demuxer
- .tid = tid,
- .stream_index = stream_index,
- .opts = demuxer->opts,
- });
- MP_TARRAY_APPEND(demuxer, demuxer->streams, demuxer->num_streams, sh);
- switch (sh->type) {
- case STREAM_VIDEO: {
- struct sh_video *sht = talloc_zero(demuxer, struct sh_video);
- sht->vid = sh->tid;
- sht->ds = demuxer->video;
- sh->video = sht;
- sh->common_header = (struct sh_common *) sht;
- demuxer->v_streams[sh->stream_index] = sht;
- break;
- }
- case STREAM_AUDIO: {
- struct sh_audio *sht = talloc_zero(demuxer, struct sh_audio);
- sht->aid = tid;
- sht->ds = demuxer->audio;
- sht->samplesize = 2;
- sht->sample_format = AF_FORMAT_S16_NE;
- sh->audio = sht;
- sh->common_header = (struct sh_common *) sht;
- demuxer->a_streams[sh->stream_index] = sht;
- break;
- }
- case STREAM_SUB: {
- struct sh_sub *sht = talloc_zero(demuxer, struct sh_sub);
- sht->sid = tid;
- sht->ds = demuxer->sub;
- sh->sub = sht;
- sh->common_header = (struct sh_common *) sht;
- demuxer->s_streams[sh->stream_index] = sht;
- break;
- }
- default: assert(false);
- }
- sh->common_header->opts = sh->opts;
- sh->common_header->gsh = sh;
- return sh;
-}
-
-sh_sub_t *new_sh_sub_sid(demuxer_t *demuxer, int id, int sid)
-{
- if (id > MAX_S_STREAMS - 1 || id < 0) {
- mp_msg(MSGT_DEMUXER, MSGL_WARN,
- "Requested sub stream id overflow (%d > %d)\n", id,
- MAX_S_STREAMS);
- return NULL;
- }
- if (demuxer->s_streams[id])
- mp_msg(MSGT_DEMUXER, MSGL_WARN, "Sub stream %i redefined\n", id);
- else {
- new_sh_stream(demuxer, STREAM_SUB, id, sid);
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SUBTITLE_ID=%d\n", sid);
- }
- return demuxer->s_streams[id];
-}
-
-struct sh_sub *new_sh_sub_sid_lang(struct demuxer *demuxer, int id, int sid,
- const char *lang)
-{
- struct sh_sub *sh = new_sh_sub_sid(demuxer, id, sid);
- if (lang && lang[0] && strcmp(lang, "und")) {
- sh->lang = talloc_strdup(sh, lang);
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", sid, lang);
- }
- return 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);
- clear_parser((sh_common_t *)sh);
- talloc_free(sh);
-}
-
-sh_audio_t *new_sh_audio_aid(demuxer_t *demuxer, int id, int aid)
-{
- if (id > MAX_A_STREAMS - 1 || id < 0) {
- mp_msg(MSGT_DEMUXER, MSGL_WARN,
- "Requested audio stream id overflow (%d > %d)\n", id,
- MAX_A_STREAMS);
- return NULL;
- }
- if (demuxer->a_streams[id]) {
- mp_tmsg(MSGT_DEMUXER, MSGL_WARN, "WARNING: Audio stream header %d redefined.\n", id);
- } else {
- mp_tmsg(MSGT_DEMUXER, MSGL_V, "==> Found audio stream: %d\n", id);
- new_sh_stream(demuxer, STREAM_AUDIO, id, aid);
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_ID=%d\n", aid);
- }
- return demuxer->a_streams[id];
-}
-
-static void free_sh_audio(demuxer_t *demuxer, int id)
-{
- sh_audio_t *sh = demuxer->a_streams[id];
- demuxer->a_streams[id] = NULL;
- mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing sh_audio at %p\n", sh);
- free(sh->wf);
- free(sh->codecdata);
- clear_parser((sh_common_t *)sh);
- talloc_free(sh);
-}
-
-sh_video_t *new_sh_video_vid(demuxer_t *demuxer, int id, int vid)
-{
- if (id > MAX_V_STREAMS - 1 || id < 0) {
- mp_msg(MSGT_DEMUXER, MSGL_WARN,
- "Requested video stream id overflow (%d > %d)\n", id,
- MAX_V_STREAMS);
- return NULL;
- }
- if (demuxer->v_streams[id])
- mp_tmsg(MSGT_DEMUXER, MSGL_WARN, "WARNING: Video stream header %d redefined.\n", id);
- else {
- mp_tmsg(MSGT_DEMUXER, MSGL_V, "==> Found video stream: %d\n", id);
- new_sh_stream(demuxer, STREAM_VIDEO, id, vid);
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_ID=%d\n", vid);
- }
- return demuxer->v_streams[id];
-}
-
-static void free_sh_video(sh_video_t *sh)
-{
- mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing sh_video at %p\n", sh);
- free(sh->bih);
- clear_parser((sh_common_t *)sh);
- talloc_free(sh);
-}
-
-void free_demuxer(demuxer_t *demuxer)
-{
- int i;
- mp_msg(MSGT_DEMUXER, MSGL_DBG2, "DEMUXER: freeing %s demuxer at %p\n",
- demuxer->desc->shortdesc, demuxer);
- if (demuxer->desc->close)
- demuxer->desc->close(demuxer);
- // free streams:
- for (i = 0; i < MAX_A_STREAMS; i++)
- if (demuxer->a_streams[i])
- free_sh_audio(demuxer, i);
- for (i = 0; i < MAX_V_STREAMS; i++)
- if (demuxer->v_streams[i])
- free_sh_video(demuxer->v_streams[i]);
- for (i = 0; i < MAX_S_STREAMS; i++)
- if (demuxer->s_streams[i])
- free_sh_sub(demuxer->s_streams[i]);
- // free demuxers:
- free_demuxer_stream(demuxer->audio);
- free_demuxer_stream(demuxer->video);
- free_demuxer_stream(demuxer->sub);
- free(demuxer->filename);
- talloc_free(demuxer);
-}
-
-
-void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp)
-{
- // append packet to DS stream:
- ++ds->packs;
- ds->bytes += dp->len;
- if (ds->last) {
- // next packet in stream
- ds->last->next = dp;
- ds->last = dp;
- } else {
- // first packet in stream
- ds->first = ds->last = dp;
- }
- mp_dbg(MSGT_DEMUXER, MSGL_DBG2,
- "DEMUX: Append packet to %s, len=%d pts=%5.3f pos=%u [packs: A=%d V=%d]\n",
- (ds == ds->demuxer->audio) ? "d_audio" : "d_video", dp->len,
- dp->pts, (unsigned int) dp->pos, ds->demuxer->audio->packs,
- ds->demuxer->video->packs);
-}
-
-static void allocate_parser(AVCodecContext **avctx, AVCodecParserContext **parser, unsigned format)
-{
- enum CodecID codec_id = CODEC_ID_NONE;
-
- switch (format) {
- case MKTAG('M', 'P', '4', 'L'):
- codec_id = CODEC_ID_AAC_LATM;
- break;
- case 0x2000:
- case 0x332D6361:
- case 0x332D4341:
- case 0x20736D:
- case MKTAG('s', 'a', 'c', '3'):
- codec_id = CODEC_ID_AC3;
- break;
- case MKTAG('d', 'n', 'e', 't'):
- // DNET/byte-swapped AC-3 - there is no parser for that yet
- //codec_id = CODEC_ID_DNET;
- break;
- case MKTAG('E', 'A', 'C', '3'):
- codec_id = CODEC_ID_EAC3;
- break;
- case 0x2001:
- case 0x86:
- codec_id = CODEC_ID_DTS;
- break;
- case MKTAG('f', 'L', 'a', 'C'):
- codec_id = CODEC_ID_FLAC;
- break;
- case MKTAG('M', 'L', 'P', ' '):
- codec_id = CODEC_ID_MLP;
- break;
- case 0x55:
- case 0x5500736d:
- case 0x55005354:
- case MKTAG('.', 'm', 'p', '3'):
- case MKTAG('M', 'P', '3', ' '):
- case MKTAG('L', 'A', 'M', 'E'):
- codec_id = CODEC_ID_MP3;
- break;
- case 0x50:
- case 0x5000736d:
- case MKTAG('.', 'm', 'p', '2'):
- case MKTAG('.', 'm', 'p', '1'):
- codec_id = CODEC_ID_MP2;
- break;
- case MKTAG('T', 'R', 'H', 'D'):
- codec_id = CODEC_ID_TRUEHD;
- break;
- }
- if (codec_id != CODEC_ID_NONE) {
- *avctx = avcodec_alloc_context3(NULL);
- if (!*avctx)
- return;
- *parser = av_parser_init(codec_id);
- if (!*parser)
- av_freep(avctx);
- }
-}
-
-static void get_parser(sh_common_t *sh, AVCodecContext **avctx, AVCodecParserContext **parser)
-{
- *avctx = NULL;
- *parser = NULL;
-
- if (!sh || !sh->needs_parsing)
- return;
-
- *avctx = sh->avctx;
- *parser = sh->parser;
- if (*parser)
- return;
-
- allocate_parser(avctx, parser, sh->format);
- sh->avctx = *avctx;
- sh->parser = *parser;
-}
-
-int ds_parse(demux_stream_t *ds, uint8_t **buffer, int *len, double pts, off_t pos)
-{
- AVCodecContext *avctx;
- AVCodecParserContext *parser;
- get_parser(ds->sh, &avctx, &parser);
- if (!parser)
- return *len;
- return av_parser_parse2(parser, avctx, buffer, len, *buffer, *len, pts, pts, pos);
-}
-
-static void clear_parser(sh_common_t *sh)
-{
- av_parser_close(sh->parser);
- sh->parser = NULL;
- av_freep(&sh->avctx);
-}
-
-void ds_clear_parser(demux_stream_t *ds)
-{
- if (!ds->sh)
- return;
- clear_parser(ds->sh);
-}
-
-void ds_read_packet(demux_stream_t *ds, stream_t *stream, int len,
- double pts, off_t pos, bool keyframe)
-{
- demux_packet_t *dp = new_demux_packet(len);
- len = stream_read(stream, dp->buffer, len);
- resize_demux_packet(dp, len);
- dp->pts = pts;
- dp->pos = pos;
- dp->keyframe = keyframe;
- // append packet to DS stream:
- ds_add_packet(ds, dp);
-}
-
-// return value:
-// 0 = EOF or no stream found or invalid type
-// 1 = successfully read a packet
-
-int demux_fill_buffer(demuxer_t *demux, demux_stream_t *ds)
-{
- // Note: parameter 'ds' can be NULL!
- return demux->desc->fill_buffer(demux, ds);
-}
-
-// return value:
-// 0 = EOF
-// 1 = successful
-int ds_fill_buffer(demux_stream_t *ds)
-{
- demuxer_t *demux = ds->demuxer;
- if (ds->current)
- free_demux_packet(ds->current);
- ds->current = NULL;
- mp_dbg(MSGT_DEMUXER, MSGL_DBG3, "ds_fill_buffer (%s) called\n",
- ds == demux->audio ? "d_audio" : ds == demux->video ? "d_video" :
- ds == demux->sub ? "d_sub" : "unknown");
- while (1) {
- if (ds->packs) {
- demux_packet_t *p = ds->first;
- // copy useful data:
- ds->buffer = p->buffer;
- ds->buffer_pos = 0;
- ds->buffer_size = p->len;
- ds->pos = p->pos;
- ds->dpos += p->len; // !!!
- ++ds->pack_no;
- if (p->pts != MP_NOPTS_VALUE) {
- ds->pts = p->pts;
- ds->pts_bytes = 0;
- }
- ds->pts_bytes += p->len; // !!!
- if (p->stream_pts != MP_NOPTS_VALUE)
- demux->stream_pts = p->stream_pts;
- ds->keyframe = p->keyframe;
- // unlink packet:
- ds->bytes -= p->len;
- ds->current = p;
- ds->first = p->next;
- 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;
- }
-
-#define MaybeNI _("Maybe you are playing a non-interleaved stream/file or the codec failed?\n" \
- "For AVI files, try to force non-interleaved mode with the --demuxer=avi --avi-ni options.\n")
-
- if (demux->audio->packs >= MAX_PACKS
- || demux->audio->bytes >= MAX_PACK_BYTES) {
- mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "\nToo many audio packets in the buffer: (%d in %d bytes).\n",
- demux->audio->packs, demux->audio->bytes);
- mp_tmsg(MSGT_DEMUXER, MSGL_HINT, MaybeNI);
- break;
- }
- if (demux->video->packs >= MAX_PACKS
- || demux->video->bytes >= MAX_PACK_BYTES) {
- mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "\nToo many video packets in the buffer: (%d in %d bytes).\n",
- demux->video->packs, demux->video->bytes);
- mp_tmsg(MSGT_DEMUXER, MSGL_HINT, MaybeNI);
- break;
- }
- if (!demux_fill_buffer(demux, ds)) {
- mp_dbg(MSGT_DEMUXER, MSGL_DBG2,
- "ds_fill_buffer()->demux_fill_buffer() failed\n");
- break; // EOF
- }
- }
- ds->buffer_pos = ds->buffer_size = 0;
- ds->buffer = NULL;
- mp_msg(MSGT_DEMUXER, MSGL_V,
- "ds_fill_buffer: EOF reached (stream: %s) \n",
- ds == demux->audio ? "audio" : "video");
- ds->eof = 1;
- return 0;
-}
-
-int demux_read_data(demux_stream_t *ds, unsigned char *mem, int len)
-{
- int x;
- int bytes = 0;
- while (len > 0) {
- x = ds->buffer_size - ds->buffer_pos;
- if (x == 0) {
- if (!ds_fill_buffer(ds))
- return bytes;
- } else {
- if (x > len)
- x = len;
- if (mem)
- memcpy(mem + bytes, &ds->buffer[ds->buffer_pos], x);
- bytes += x;
- len -= x;
- ds->buffer_pos += x;
- }
- }
- return bytes;
-}
-
-/**
- * \brief read data until the given 3-byte pattern is encountered, up to maxlen
- * \param mem memory to read data into, may be NULL to discard data
- * \param maxlen maximum number of bytes to read
- * \param read number of bytes actually read
- * \param pattern pattern to search for (lowest 8 bits are ignored)
- * \return whether pattern was found
- */
-int demux_pattern_3(demux_stream_t *ds, unsigned char *mem, int maxlen,
- int *read, uint32_t pattern)
-{
- register uint32_t head = 0xffffff00;
- register uint32_t pat = pattern & 0xffffff00;
- int total_len = 0;
- do {
- register unsigned char *ds_buf = &ds->buffer[ds->buffer_size];
- int len = ds->buffer_size - ds->buffer_pos;
- register long pos = -len;
- if (unlikely(pos >= 0)) { // buffer is empty
- ds_fill_buffer(ds);
- continue;
- }
- do {
- head |= ds_buf[pos];
- head <<= 8;
- } while (++pos && head != pat);
- len += pos;
- if (total_len + len > maxlen)
- len = maxlen - total_len;
- len = demux_read_data(ds, mem ? &mem[total_len] : NULL, len);
- total_len += len;
- } while ((head != pat || total_len < 3) && total_len < maxlen && !ds->eof);
- if (read)
- *read = total_len;
- return total_len >= 3 && head == pat;
-}
-
-void ds_free_packs(demux_stream_t *ds)
-{
- demux_packet_t *dp = ds->first;
- while (dp) {
- demux_packet_t *dn = dp->next;
- free_demux_packet(dp);
- dp = dn;
- }
- if (ds->asf_packet) {
- // free unfinished .asf fragments:
- free(ds->asf_packet->buffer);
- free(ds->asf_packet);
- ds->asf_packet = NULL;
- }
- ds->first = ds->last = NULL;
- ds->packs = 0; // !!!!!
- ds->bytes = 0;
- if (ds->current)
- free_demux_packet(ds->current);
- ds->current = NULL;
- ds->buffer = NULL;
- ds->buffer_pos = ds->buffer_size;
- ds->pts = MP_NOPTS_VALUE;
- ds->pts_bytes = 0;
-}
-
-int ds_get_packet(demux_stream_t *ds, unsigned char **start)
-{
- int len;
- if (ds->buffer_pos >= ds->buffer_size) {
- if (!ds_fill_buffer(ds)) {
- // EOF
- *start = NULL;
- return -1;
- }
- }
- len = ds->buffer_size - ds->buffer_pos;
- *start = &ds->buffer[ds->buffer_pos];
- ds->buffer_pos += len;
- return len;
-}
-
-int ds_get_packet_pts(demux_stream_t *ds, unsigned char **start, double *pts)
-{
- int len;
- *pts = MP_NOPTS_VALUE;
- len = ds_get_packet(ds, start);
- if (len < 0)
- return len;
- // Return pts unless this read starts from the middle of a packet
- if (len == ds->buffer_pos)
- *pts = ds->current->pts;
- return len;
-}
-
-int ds_get_packet_sub(demux_stream_t *ds, unsigned char **start)
-{
- int len;
- if (ds->buffer_pos >= ds->buffer_size) {
- *start = NULL;
- if (!ds->packs)
- return -1; // no sub
- if (!ds_fill_buffer(ds))
- return -1; // EOF
- }
- len = ds->buffer_size - ds->buffer_pos;
- *start = &ds->buffer[ds->buffer_pos];
- ds->buffer_pos += len;
- return len;
-}
-
-struct demux_packet *ds_get_packet2(struct demux_stream *ds, bool repeat_last)
-{
- // This shouldn't get used together with partial reads
- assert(ds->buffer_pos == 0 || ds->buffer_pos >= ds->buffer_size);
- if (!repeat_last)
- ds_fill_buffer(ds);
- ds->buffer_pos = ds->buffer_size;
- return ds->current;
-}
-
-double ds_get_next_pts(demux_stream_t *ds)
-{
- demuxer_t *demux = ds->demuxer;
- // if we have not read from the "current" packet, consider it
- // as the next, otherwise we never get the pts for the first packet.
- while (!ds->first && (!ds->current || ds->buffer_pos)) {
- if (demux->audio->packs >= MAX_PACKS
- || demux->audio->bytes >= MAX_PACK_BYTES) {
- mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "\nToo many audio packets in the buffer: (%d in %d bytes).\n",
- demux->audio->packs, demux->audio->bytes);
- mp_tmsg(MSGT_DEMUXER, MSGL_HINT, MaybeNI);
- return MP_NOPTS_VALUE;
- }
- if (demux->video->packs >= MAX_PACKS
- || demux->video->bytes >= MAX_PACK_BYTES) {
- mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "\nToo many video packets in the buffer: (%d in %d bytes).\n",
- demux->video->packs, demux->video->bytes);
- mp_tmsg(MSGT_DEMUXER, MSGL_HINT, MaybeNI);
- return MP_NOPTS_VALUE;
- }
- if (!demux_fill_buffer(demux, ds))
- return MP_NOPTS_VALUE;
- }
- // take pts from "current" if we never read from it.
- if (ds->current && !ds->buffer_pos)
- return ds->current->pts;
- return ds->first->pts;
-}
-
-// ====================================================================
-
-void demuxer_help(void)
-{
- int i;
-
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "Available demuxers:\n");
- mp_msg(MSGT_DEMUXER, MSGL_INFO, " demuxer: info: (comment)\n");
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DEMUXERS\n");
- for (i = 0; demuxer_list[i]; i++) {
- if (demuxer_list[i]->type >= DEMUXER_TYPE_END) // internal type
- continue;
- if (demuxer_list[i]->comment && strlen(demuxer_list[i]->comment))
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "%10s %s (%s)\n",
- demuxer_list[i]->name, demuxer_list[i]->info,
- demuxer_list[i]->comment);
- else
- mp_msg(MSGT_DEMUXER, MSGL_INFO, "%10s %s\n",
- demuxer_list[i]->name, demuxer_list[i]->info);
- }
-}
-
-
-/**
- * Get demuxer type for a given demuxer name
- *
- * @param demuxer_name string with demuxer name of demuxer number
- * @param force will be set if demuxer should be forced.
- * May be NULL.
- * @return DEMUXER_TYPE_xxx, -1 if error or not found
- */
-static int get_demuxer_type_from_name(char *demuxer_name, int *force)
-{
- if (!demuxer_name || !demuxer_name[0])
- return DEMUXER_TYPE_UNKNOWN;
- if (force)
- *force = demuxer_name[0] == '+';
- if (demuxer_name[0] == '+')
- demuxer_name = &demuxer_name[1];
- for (int i = 0; demuxer_list[i]; i++) {
- if (demuxer_list[i]->type >= DEMUXER_TYPE_END)
- // Can't select special demuxers from commandline
- continue;
- if (strcmp(demuxer_name, demuxer_list[i]->name) == 0)
- return demuxer_list[i]->type;
- }
-
- return -1;
-}
-
-static struct demuxer *open_given_type(struct MPOpts *opts,
- const struct demuxer_desc *desc,
- struct stream *stream, bool force,
- int audio_id, int video_id, int sub_id,
- char *filename,
- struct demuxer_params *params)
-{
- struct demuxer *demuxer;
- int fformat;
- demuxer = new_demuxer(opts, stream, desc->type, audio_id,
- video_id, sub_id, filename);
- demuxer->params = params;
- if (desc->check_file)
- fformat = desc->check_file(demuxer);
- else
- fformat = desc->type;
- if (force)
- fformat = desc->type;
- if (fformat == 0)
- goto fail;
- if (fformat == desc->type) {
- if (demuxer->filetype)
- mp_tmsg(MSGT_DEMUXER, MSGL_INFO, "Detected file format: %s (%s)\n",
- demuxer->filetype, desc->shortdesc);
- else
- mp_tmsg(MSGT_DEMUXER, MSGL_INFO, "Detected file format: %s\n",
- desc->shortdesc);
- if (demuxer->desc->open) {
- struct demuxer *demux2 = demuxer->desc->open(demuxer);
- if (!demux2) {
- mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "Opening as detected format "
- "\"%s\" failed.\n", desc->shortdesc);
- goto fail;
- }
- /* At least demux_mov can return a demux_demuxers instance
- * from open() instead of the original fed in. */
- demuxer = demux2;
- }
- demuxer->file_format = fformat;
- opts->correct_pts = opts->user_correct_pts;
- if (opts->correct_pts < 0)
- opts->correct_pts =
- demux_control(demuxer, DEMUXER_CTRL_CORRECT_PTS,
- NULL) == DEMUXER_CTRL_OK;
- return demuxer;
- } else {
- // demux_mov can return playlist instead of mov
- if (fformat == DEMUXER_TYPE_PLAYLIST)
- return demuxer; // handled in mplayer.c
- /* Internal MPEG PS demuxer check can return other MPEG subtypes
- * which don't have their own checks; recurse to try opening as
- * the returned type instead. */
- free_demuxer(demuxer);
- desc = get_demuxer_desc_from_type(fformat);
- if (!desc) {
- mp_msg(MSGT_DEMUXER, MSGL_ERR,
- "BUG: recursion to nonexistent file format\n");
- return NULL;
- }
- return open_given_type(opts, desc, stream, false, audio_id,
- video_id, sub_id, filename, params);
- }
- fail:
- free_demuxer(demuxer);
- return NULL;
-}
-
-struct demuxer *demux_open_withparams(struct MPOpts *opts,
- struct stream *stream, int file_format,
- char *force_format, int audio_id,
- int video_id, int sub_id, char *filename,
- struct demuxer_params *params)
-{
- struct demuxer *demuxer = NULL;
- const struct demuxer_desc *desc;
-
- int force = 0;
- int demuxer_type;
- if ((demuxer_type = get_demuxer_type_from_name(force_format, &force)) < 0) {
- mp_msg(MSGT_DEMUXER, MSGL_ERR, "Demuxer %s does not exist.\n",