summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
Diffstat (limited to 'demux')
-rw-r--r--demux/demux.c178
-rw-r--r--demux/demux.h28
-rw-r--r--demux/demux_mng.c15
-rw-r--r--demux/demux_rawvideo.c1
4 files changed, 70 insertions, 152 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;
}
// ====================================================================
diff --git a/demux/demux.h b/demux/demux.h
index eb5de265b3..fade7533e9 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -90,19 +90,15 @@ enum timestamp_type {
typedef struct demux_stream {
enum stream_type stream_type;
- 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);
- double pts; // current buffer's pts
- int pts_bytes; // number of bytes read after last pts stamp
+ double last_pts; // pts of the last packet that was read
+ int last_pts_bytes; // number of bytes read after last pts stamp
int eof; // end of demuxed stream? (true if all buffer empty)
//---------------
int fill_count; // number of unsuccessful tries to get a packet
int packs; // number of packets in buffer
int bytes; // total bytes of packets in buffer
- demux_packet_t *first; // read to current buffer from here
- demux_packet_t *last; // append new packets from input stream to here
- demux_packet_t *current; // needed for refcounting of the buffer
+ struct demux_packet *head;
+ struct demux_packet *tail;
struct demuxer *demuxer; // parent demuxer structure (stream handler)
// ---- stream header ----
struct sh_stream *gsh;
@@ -256,20 +252,12 @@ int demuxer_add_packet(demuxer_t *demuxer, struct sh_stream *stream,
void ds_add_packet(struct demux_stream *ds, struct demux_packet *dp);
int demux_fill_buffer(struct demuxer *demux, struct demux_stream *ds);
-int ds_fill_buffer(struct demux_stream *ds);
-
-static inline int ds_tell_pts(struct demux_stream *ds)
-{
- return (ds->pts_bytes - ds->buffer_size) + ds->buffer_pos;
-}
void ds_free_packs(struct demux_stream *ds);
-int ds_get_packet(struct demux_stream *ds, unsigned char **start);
-int ds_get_packet_pts(struct demux_stream *ds, unsigned char **start,
- double *pts);
-struct demux_packet *ds_get_packet_sub(demux_stream_t *ds);
-struct demux_packet *ds_get_packet2(struct demux_stream *ds, bool repeat_last);
-double ds_get_next_pts(struct demux_stream *ds);
+
+struct demux_packet *demux_read_packet(struct sh_stream *sh);
+double demux_get_next_pts(struct sh_stream *sh);
+bool demux_has_packet(struct sh_stream *sh);
struct demuxer *demux_open(struct MPOpts *opts, struct stream *stream,
int file_format, char *filename);
diff --git a/demux/demux_mng.c b/demux/demux_mng.c
index 76b742f019..6dc0e352e8 100644
--- a/demux/demux_mng.c
+++ b/demux/demux_mng.c
@@ -38,14 +38,6 @@
#include <libmng.h>
/**
- * \brief some small fixed start time > 0
- *
- * Start time must be > 0 for the variable frame time mechanism
- * (GIF, MATROSKA, MNG) in video.c to work for the first frame.
- */
-#define MNG_START_PTS 0.01f
-
-/**
* \brief private context structure
*
* This structure is used as private data for MPlayer demuxer
@@ -346,7 +338,7 @@ static int demux_mng_fill_buffer(demuxer_t * demuxer,
// Set position and timing information in demuxer video and demuxer packet.
// - Time must be time of next frame and always be > 0 for the variable
// frame time mechanism (GIF, MATROSKA, MNG) in video.c to work.
- dp->pts = (float)mng_priv->show_next_time_ms / 1000.0f + MNG_START_PTS;
+ dp->pts = (float)mng_priv->show_next_time_ms / 1000.0f;
dp->pos = stream_tell(demuxer->stream);
ds_add_packet(demuxer->video, dp);
@@ -447,11 +439,6 @@ static demuxer_t * demux_mng_open(demuxer_t * demuxer)
sh_video->bih->biBitCount = 32;
sh_video->bih->biPlanes = 1;
- // Set start time to something > 0.
- // - This is required for the variable frame time mechanism
- // (GIF, MATROSKA, MNG) in video.c to work for the first frame.
- sh_video->ds->pts = MNG_START_PTS;
-
// set private data in demuxer and return demuxer
demuxer->priv = mng_priv;
return demuxer;
diff --git a/demux/demux_rawvideo.c b/demux/demux_rawvideo.c
index a4eaaa2a8c..787bd0c064 100644
--- a/demux/demux_rawvideo.c
+++ b/demux/demux_rawvideo.c
@@ -164,7 +164,6 @@ static void demux_rawvideo_seek(demuxer_t *demuxer,float rel_seek_secs,float aud
pos/=imgsize;
stream_seek(s,pos*imgsize);
//sh_video->timer=pos * sh_video->frametime;
- demuxer->video->pts = pos * sh_video->frametime;
// printf("demux_rawvideo: streamtell=%d\n",(int)stream_tell(demuxer->stream));
}