summaryrefslogtreecommitdiffstats
path: root/demux/demux.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-07-11 19:10:33 +0200
committerwm4 <wm4@nowhere>2013-07-11 19:10:33 +0200
commita5224836293ac02bd13f688cfc848aae6818e963 (patch)
treec67c9a61505583a0614ccc2c7cdbdb4e1deffda2 /demux/demux.c
parent07c5327fa0c3411bcb8caad17d70b014d6b022dd (diff)
downloadmpv-a5224836293ac02bd13f688cfc848aae6818e963.tar.bz2
mpv-a5224836293ac02bd13f688cfc848aae6818e963.tar.xz
demux: remove facility for partial packet reads
Partial packet reads were needed because the video/audio parsers were working on top of them. So it could happen that a parser read a part of a packet, and returned that to the decoder. With libavformat/libavcodec, packets are already parsed, and everything is much simpler. Most of the simplifications in ad_spdif could have been done earlier. Remove some other stuff as well, like the questionable slave mode start time reporting (could be replaced by proper code, but we don't bother). Remove the unused skip_audio_frame() functionality as well (it was used by old demuxers). Some functions become private to demux.c, like demux_fill_buffer(). Introduce new packet read functions, which have simpler semantics. Packets returned from them are owned by the caller, and all packets in the demux.c packet queue are considered unread. Remove special code that dropped subtitle packets with size 0. This used to be needed because it caused special cases in the old code.
Diffstat (limited to 'demux/demux.c')
-rw-r--r--demux/demux.c178
1 files changed, 61 insertions, 117 deletions
diff --git a/demux/demux.c b/demux/demux.c
index f0cb28ab1d..16adfeb795 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -375,26 +375,16 @@ int demuxer_add_packet(demuxer_t *demuxer, struct sh_stream *stream,
void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp)
{
- // demux API can't handle 0-sized packets, but at least some vobsubs
- // generate them. Skipping them seems to work fine. Not skipping them will
- // stop demuxing with external vobsubs. See FATE sub/vobsub.{idx,sub} at
- // pts=185.91.
- if (dp->len == 0 && ds->stream_type == STREAM_SUB) {
- mp_dbg(MSGT_DEMUXER, MSGL_INFO, "Discarding empty subtitle packet.\n");
- free_demux_packet(dp);
- return;
- }
-
// append packet to DS stream:
++ds->packs;
ds->bytes += dp->len;
- if (ds->last) {
+ if (ds->tail) {
// next packet in stream
- ds->last->next = dp;
- ds->last = dp;
+ ds->tail->next = dp;
+ ds->tail = dp;
} else {
// first packet in stream
- ds->first = ds->last = dp;
+ ds->head = ds->tail = 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",
@@ -440,38 +430,18 @@ int demux_fill_buffer(demuxer_t *demux, demux_stream_t *ds)
// return value:
// 0 = EOF
// 1 = successful
-int ds_fill_buffer(demux_stream_t *ds)
+static int ds_get_packets(demux_stream_t *ds)
{
+ if (!ds)
+ return 0;
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",
+ mp_dbg(MSGT_DEMUXER, MSGL_DBG3, "ds_get_packets (%s) called\n",
ds == demux->audio ? "d_audio" : ds == demux->video ? "d_video" :
ds == demux->sub ? "d_sub" : "unknown");
while (1) {
int apacks = demux->audio ? demux->audio->packs : 0;
int vpacks = demux->video ? demux->video->packs : 0;
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;
- 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;
- // 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
@@ -497,7 +467,7 @@ int ds_fill_buffer(demux_stream_t *ds)
if (!demux_fill_buffer(demux, ds)) {
mp_dbg(MSGT_DEMUXER, MSGL_DBG2,
- "ds_fill_buffer()->demux_fill_buffer() failed\n");
+ "ds_get_packets()->demux_fill_buffer() failed\n");
break; // EOF
}
@@ -508,10 +478,8 @@ int ds_fill_buffer(demux_stream_t *ds)
ds->fill_count++;
}
}
- 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_get_packets: EOF reached (stream: %s) \n",
ds == demux->audio ? "audio" : "video");
ds->eof = 1;
return 0;
@@ -519,100 +487,76 @@ int ds_fill_buffer(demux_stream_t *ds)
void ds_free_packs(demux_stream_t *ds)
{
- demux_packet_t *dp = ds->first;
+ demux_packet_t *dp = ds->head;
while (dp) {
demux_packet_t *dn = dp->next;
free_demux_packet(dp);
dp = dn;
}
- ds->first = ds->last = NULL;
+ ds->head = ds->tail = 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;
+ ds->last_pts = MP_NOPTS_VALUE;
+ ds->last_pts_bytes = 0;
}
-int ds_get_packet_pts(demux_stream_t *ds, unsigned char **start, double *pts)
+static struct demux_stream *ds_from_sh(struct sh_stream *sh)
{
- 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;
+ for (int n = 0; n < STREAM_TYPE_COUNT; n++) {
+ if (sh->demuxer->ds[n]->gsh == sh)
+ return sh->demuxer->ds[n];
+ }
+ return NULL;
}
-struct demux_packet *ds_get_packet_sub(demux_stream_t *ds)
-{
- if (ds->buffer_pos >= ds->buffer_size) {
- if (!ds->packs)
- return NULL; // no sub
- if (!ds_fill_buffer(ds))
- return NULL; // EOF
- }
- if (ds->buffer_pos < ds->buffer_size) {
- ds->current->buffer += ds->buffer_pos;
- ds->buffer_size -= ds->buffer_pos;
+// Read a packet from the given stream. The returned packet belongs to the
+// caller, who has to free it with talloc_free(). Might block. Returns NULL
+// on EOF.
+struct demux_packet *demux_read_packet(struct sh_stream *sh)
+{
+ struct demux_stream *ds = ds_from_sh(sh);
+ if (ds) {
+ ds_get_packets(ds);
+ struct demux_packet *pkt = ds->head;
+ if (pkt) {
+ ds->head = pkt->next;
+ pkt->next = NULL;
+ if (!ds->head)
+ ds->tail = NULL;
+ ds->bytes -= pkt->len;
+ ds->packs--;
+
+ if (pkt->pts != MP_NOPTS_VALUE) {
+ ds->last_pts = pkt->pts;
+ ds->last_pts_bytes = 0;
+ } else {
+ ds->last_pts_bytes += pkt->len;
+ }
+
+ if (pkt->stream_pts != MP_NOPTS_VALUE)
+ sh->demuxer->stream_pts = pkt->stream_pts;
+
+ return pkt;
+ }
}
- ds->buffer_pos = ds->buffer_size;
- return ds->current;
+ return NULL;
}
-struct demux_packet *ds_get_packet2(struct demux_stream *ds, bool repeat_last)
+// Return the pts of the next packet that demux_read_packet() would return.
+// Might block. Sometimes used to force a packet read, without removing any
+// packets from the queue.
+double demux_get_next_pts(struct sh_stream *sh)
{
- if (!repeat_last)
- ds_fill_buffer(ds);
- // This shouldn't get used together with partial reads
- // However, some old demuxers return parsed packets with an offset in
- // -correct-pts mode (at least mpegts).
- // Not all old demuxers will actually work.
- if (ds->buffer_pos < ds->buffer_size) {
- ds->current->buffer += ds->buffer_pos;
- ds->buffer_size -= ds->buffer_pos;
- }
- ds->buffer_pos = ds->buffer_size;
- return ds->current;
+ struct demux_stream *ds = ds_from_sh(sh);
+ ds_get_packets(ds);
+ return ds && ds->head ? ds->head->pts : MP_NOPTS_VALUE;
}
-double ds_get_next_pts(demux_stream_t *ds)
+// Return whether a packet is queued. Never blocks, never forces any reads.
+bool demux_has_packet(struct sh_stream *sh)
{
- 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_check_queue_full(demux))
- 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;
+ struct demux_stream *ds = ds_from_sh(sh);
+ return ds && ds->head;
}
// ====================================================================