summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/demuxers/demux_avi.c375
1 files changed, 288 insertions, 87 deletions
diff --git a/src/demuxers/demux_avi.c b/src/demuxers/demux_avi.c
index 47acd0d21..4050919d2 100644
--- a/src/demuxers/demux_avi.c
+++ b/src/demuxers/demux_avi.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: demux_avi.c,v 1.83 2002/05/12 12:13:28 tmattern Exp $
+ * $Id: demux_avi.c,v 1.84 2002/05/13 15:56:54 miguelfreitas Exp $
*
* demultiplexer for avi streams
*
@@ -26,6 +26,28 @@
*
*/
+/*
+ * Ian Goldberg <ian@cypherpunks.ca> modified this code so that it can
+ * handle "streaming" AVI files. By that I mean real seekable files, but
+ * ones that are growing as we're displaying them. Examples include
+ * AVI's you're downloading, or ones you're writing in real time using
+ * xawtv streamer, or whatever. This latter is really useful, for
+ * example, for doing the PVR trick of starting the streamer to record
+ * TV, starting to watch it ~10 minutes later, and skipping the
+ * commercials to catch up to real time. If you accidentally hit the
+ * end of the stream, just hit your "back 15 seconds" key, and all is
+ * good.
+ *
+ * Theory of operation: the video and audio indices have been separated
+ * out of the main avi_t and avi_audio_t structures into separate
+ * structures that can grow during playback. We use the idx_grow_t
+ * structure to keep track of the offset into the AVI file where we
+ * expect to find the next A/V frame. We periodically check if we can
+ * read data from the file at that offset. If we can, we append index
+ * data for as many frames as we can read at the time.
+ *
+ */
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -66,6 +88,30 @@ typedef struct
long tot;
} audio_index_entry_t;
+/* These next three are the video and audio structures that can grow
+ * during the playback of a streaming file. */
+
+typedef struct
+{
+ long video_frames; /* Number of video frames */
+ long alloc_frames; /* Allocated number of frames */
+ video_index_entry_t *vindex;
+} video_index_t;
+
+typedef struct
+{
+ long audio_chunks; /* Chunks of audio data in the file */
+ long alloc_chunks; /* Allocated number of chunks */
+ audio_index_entry_t *aindex;
+} audio_index_t;
+
+typedef struct
+{
+ off_t nexttagoffset; /* The offset into the AVI file where we expect */
+ /* to find the next A/V frame */
+} idx_grow_t;
+
+
typedef struct
{
long dwScale_audio, dwRate_audio;
@@ -78,8 +124,6 @@ typedef struct
long a_rate; /* Rate in Hz */
long a_bits; /* bits per audio sample */
long audio_strn; /* Audio stream number */
- long audio_bytes; /* Total number of bytes of audio data */
- long audio_chunks; /* Chunks of audio data in the file */
char audio_tag[4]; /* Tag of audio data */
long audio_posc; /* Audio position: chunk */
long audio_posb; /* Audio position: byte within chunk */
@@ -87,7 +131,7 @@ typedef struct
char *wavex;
int wavex_len;
- audio_index_entry_t *audio_index;
+ audio_index_t audio_idx;
} avi_audio_t;
@@ -100,7 +144,6 @@ typedef struct
char compressor[8]; /* Type of compressor, 4 bytes + padding for 0 byte */
long video_strn; /* Video stream number */
- long video_frames; /* Number of video frames */
char video_tag[4]; /* Tag of video data */
long video_posf; /* Number of next frame to be read
(if index present) */
@@ -109,6 +152,7 @@ typedef struct
avi_audio_t *audio[MAX_AUDIO_STREAMS];
int n_audio;
+ long audio_tot; /* Total number of audio bytes */
uint32_t video_type; /* BUF_VIDEO_xxx type */
@@ -116,7 +160,7 @@ typedef struct
long n_idx; /* number of index entries actually filled */
long max_idx; /* number of index entries actually allocated */
unsigned char (*idx)[16]; /* index entries (AVI idx1 tag) */
- video_index_entry_t *video_index;
+ video_index_t video_idx;
BITMAPINFOHEADER bih;
off_t movi_start;
} avi_t;
@@ -150,6 +194,8 @@ typedef struct demux_avi_s {
int send_end_buffers;
char last_mrl[1024];
+
+ idx_grow_t idx_grow;
} demux_avi_t ;
#define AVI_ERR_SIZELIM 1 /* The write of the data would exceed
@@ -193,6 +239,55 @@ typedef struct demux_avi_s {
getIndex==0, but an operation has been
performed that needs an index */
+/* Append an index entry for a newly-found video frame */
+static int video_index_append(avi_t *AVI, long pos, long len, long flags)
+{
+ video_index_t *vit = &(AVI->video_idx);
+
+ /* Make sure there's room */
+ if (vit->video_frames == vit->alloc_frames) {
+ long newalloc = vit->alloc_frames + 4096;
+ video_index_entry_t *newindex =
+ realloc(vit->vindex, newalloc*sizeof(video_index_entry_t));
+ if (!newindex) return -1;
+ vit->vindex = newindex;
+ vit->alloc_frames = newalloc;
+ }
+
+ /* Set the new index entry */
+ vit->vindex[vit->video_frames].pos = pos;
+ vit->vindex[vit->video_frames].len = len;
+ vit->vindex[vit->video_frames].flags = flags;
+ vit->video_frames += 1;
+
+ return 0;
+}
+
+/* Append an index entry for a newly-found audio frame */
+static int audio_index_append(avi_t *AVI, int stream, long pos, long len,
+ long tot)
+{
+ audio_index_t *ait = &(AVI->audio[stream]->audio_idx);
+
+ /* Make sure there's room */
+ if (ait->audio_chunks == ait->alloc_chunks) {
+ long newalloc = ait->alloc_chunks + 4096;
+ audio_index_entry_t *newindex =
+ realloc(ait->aindex, newalloc*sizeof(audio_index_entry_t));
+ if (!newindex) return -1;
+ ait->aindex = newindex;
+ ait->alloc_chunks = newalloc;
+ }
+
+ /* Set the new index entry */
+ ait->aindex[ait->audio_chunks].pos = pos;
+ ait->aindex[ait->audio_chunks].len = len;
+ ait->aindex[ait->audio_chunks].tot = tot;
+ ait->audio_chunks += 1;
+
+ return 0;
+}
+
static unsigned long str2ulong(unsigned char *str)
{
return ( str[0] | (str[1]<<8) | (str[2]<<16) | (str[3]<<24) );
@@ -211,15 +306,103 @@ static void long2str(unsigned char *dst, int n)
dst[3] = (n>>24)&0xff;
}
+#define PAD_EVEN(x) ( ((x)+1) & ~1 )
+
+/* This is called periodically to check if there's more file now than
+ * there was before. If there is, we constuct the index for (just) the
+ * new part, and append it to the index we've got so far. */
+void idx_grow(demux_avi_t *this)
+{
+ unsigned long n;
+ long i;
+ long ioff = 8;
+ char data[256];
+ off_t curpos = this->input->seek(this->input, 0, SEEK_CUR);
+ this->input->seek(this->input, this->idx_grow.nexttagoffset, SEEK_SET);
+
+ while(1) {
+ if( this->input->read(this->input, data,8) != 8 )
+ break;
+ n = str2ulong(data+4);
+
+ /* The movi list may contain sub-lists, ignore them */
+
+ if(strncasecmp(data,"LIST",4)==0) {
+ this->idx_grow.nexttagoffset =
+ this->input->seek(this->input, 4,SEEK_CUR);
+ continue;
+ }
+
+ /* Check if we got a tag ##db, ##dc or ##wb */
+
+ if (strncasecmp(data, this->avi->video_tag, 3) == 0 &&
+ (data[3]=='b' || data[3]=='B' || data[3]=='c' || data[3]=='C') ) {
+ long flags = AVIIF_KEYFRAME;
+ long pos = this->idx_grow.nexttagoffset + ioff;
+ long len = n;
+ if (video_index_append(this->avi, pos, len, flags) == -1) {
+ /* If we're out of memory, we just don't grow the index, but
+ * nothing really bad happens. */
+ }
+ }
+ for(i=0; i < this->avi->n_audio; ++i) {
+ if (strncasecmp(data, this->avi->audio[i]->audio_tag, 4) == 0) {
+ long pos = this->idx_grow.nexttagoffset + ioff;
+ long len = n;
+ if (audio_index_append(this->avi, i, pos, len,
+ this->avi->audio_tot) == -1) {
+ /* As above. */
+ }
+ this->avi->audio_tot += len;
+ }
+ }
+
+ this->idx_grow.nexttagoffset =
+ this->input->seek(this->input, PAD_EVEN(n), SEEK_CUR);
+ }
+ this->input->seek(this->input, curpos, SEEK_SET);
+
+}
+
+/* Fetch the current video index entry, growing the index if necessary. */
+static video_index_entry_t *video_cur_index_entry(demux_avi_t *this)
+{
+ avi_t *AVI = this->avi;
+ if (AVI->video_posf >= AVI->video_idx.video_frames) {
+ /* We don't have enough frames; see if the file's bigger yet. */
+ idx_grow(this);
+ }
+ if (AVI->video_posf >= AVI->video_idx.video_frames) {
+ /* We still don't have enough frames. Oh, well. */
+ return NULL;
+ }
+ return &(AVI->video_idx.vindex[AVI->video_posf]);
+}
+
+/* Fetch the current audio index entry, growing the index if necessary. */
+static audio_index_entry_t *audio_cur_index_entry(demux_avi_t *this,
+ avi_audio_t *AVI_A)
+{
+ if (AVI_A->audio_posc >= AVI_A->audio_idx.audio_chunks) {
+ /* We don't have enough chunks; see if the file's bigger yet. */
+ idx_grow(this);
+ }
+ if (AVI_A->audio_posc >= AVI_A->audio_idx.audio_chunks) {
+ /* We still don't have enough chunks. Oh, well. */
+ return NULL;
+ }
+ return &(AVI_A->audio_idx.aindex[AVI_A->audio_posc]);
+}
+
static void AVI_close(avi_t *AVI)
{
int i;
if(AVI->idx) free(AVI->idx);
- if(AVI->video_index) free(AVI->video_index);
+ if(AVI->video_idx.vindex) free(AVI->video_idx.vindex);
for(i=0; i<AVI->n_audio; i++) {
- if(AVI->audio[i]->audio_index) free(AVI->audio[i]->audio_index);
+ if(AVI->audio[i]->audio_idx.aindex) free(AVI->audio[i]->audio_idx.aindex);
if(AVI->audio[i]->wavex) free(AVI->audio[i]->wavex);
free(AVI->audio[i]);
}
@@ -233,8 +416,6 @@ do { \
return 0; \
} while(0)
-#define PAD_EVEN(x) ( ((x)+1) & ~1 )
-
static int avi_sampsize(avi_t *AVI, int track)
{
int s;
@@ -292,8 +473,7 @@ static avi_t *AVI_init(demux_avi_t *this) {
long i, n, idx_type;
unsigned char *hdrl_data;
long hdrl_len=0;
- long nvi, nai[MAX_AUDIO_STREAMS], ioff;
- long tot;
+ long ioff;
int lasttag = 0;
int vids_strh_seen = 0;
int vids_strf_seen = 0;
@@ -328,6 +508,10 @@ static avi_t *AVI_init(demux_avi_t *this) {
while(1) {
+ /* Keep track of where we try to read frames from. */
+ this->idx_grow.nexttagoffset =
+ this->input->seek(this->input, 0, SEEK_CUR);
+
if (this->input->read(this->input, data,8) != 8 )
break; /* We assume it's EOF */
@@ -411,7 +595,6 @@ static avi_t *AVI_init(demux_avi_t *this) {
this->video_step = (long) (90000.0 / AVI->fps);
- AVI->video_frames = str2ulong(hdrl_data+i+32);
AVI->video_strn = num_stream;
vids_strh_seen = 1;
lasttag = 1; /* vids */
@@ -425,7 +608,6 @@ static avi_t *AVI_init(demux_avi_t *this) {
memset((void *)a,0,sizeof(avi_audio_t));
AVI->audio[AVI->n_audio] = a;
- a->audio_bytes = str2ulong(hdrl_data+i+32)*avi_sampsize(AVI, AVI->n_audio);
a->audio_strn = num_stream;
a->dwScale_audio = str2ulong(hdrl_data+i+20);
a->dwRate_audio = str2ulong(hdrl_data+i+24);
@@ -479,7 +661,7 @@ static avi_t *AVI_init(demux_avi_t *this) {
hdrl_data = NULL;
/* somehow ffmpeg doesn't specify the number of frames here */
- /* if (!vids_strh_seen || !vids_strf_seen || AVI->video_frames==0) { */
+ /* if (!vids_strh_seen || !vids_strf_seen || AVI->video_frames==0) */
if (!vids_strh_seen || !vids_strf_seen)
ERR_EXIT(AVI_ERR_NO_VIDS);
@@ -543,7 +725,8 @@ static avi_t *AVI_init(demux_avi_t *this) {
if(idx_type == 0) {
/* we must search through the file to get the index */
- this->input->seek(this->input, AVI->movi_start, SEEK_SET);
+ this->idx_grow.nexttagoffset =
+ this->input->seek(this->input, AVI->movi_start, SEEK_SET);
AVI->n_idx = 0;
i=0;
@@ -572,7 +755,8 @@ static avi_t *AVI_init(demux_avi_t *this) {
/* The movi list may contain sub-lists, ignore them */
if(strncasecmp(data,"LIST",4)==0) {
- this->input->seek(this->input, 4,SEEK_CUR);
+ this->idx_grow.nexttagoffset =
+ this->input->seek(this->input, 4,SEEK_CUR);
continue;
}
@@ -585,8 +769,8 @@ static avi_t *AVI_init(demux_avi_t *this) {
avi_add_index_entry(this, AVI, data, AVIIF_KEYFRAME, this->input->seek(this->input, 0, SEEK_CUR)-8, n);
}
- this->input->seek(this->input, PAD_EVEN(n), SEEK_CUR);
-
+ this->idx_grow.nexttagoffset =
+ this->input->seek(this->input, PAD_EVEN(n), SEEK_CUR);
}
printf ("\ndemux_avi: index recostruction done.\n");
this->xine->osd_renderer->hide (this->xine->osd, 0);
@@ -595,54 +779,32 @@ static avi_t *AVI_init(demux_avi_t *this) {
/* Now generate the video index and audio index arrays */
- nvi = 0;
- memset((void *)nai,0,sizeof(long) * MAX_AUDIO_STREAMS);
-
- for(i=0;i<AVI->n_idx;i++) {
- if(strncasecmp(AVI->idx[i],AVI->video_tag,3) == 0) nvi++;
- for(n = 0; n < AVI->n_audio; n++)
- if(strncasecmp(AVI->idx[i],AVI->audio[n]->audio_tag,4) == 0) nai[n]++;
- }
-
- AVI->video_frames = nvi;
- for(n = 0; n < AVI->n_audio; n++)
- AVI->audio[n]->audio_chunks = nai[n];
-
- if (AVI->video_frames==0) {
- ERR_EXIT(AVI_ERR_NO_VIDS) ;
- }
+ /* Note that we no longer need to do two passes. Technically, we
+ * don't even have to construct the idx, but we may as well use the
+ * one we were given, if in fact we were given one. */
-
- AVI->video_index = (video_index_entry_t *) xine_xmalloc(nvi*sizeof(video_index_entry_t));
- if(AVI->video_index==0) ERR_EXIT(AVI_ERR_NO_MEM) ;
-
- for(n = 0; n < AVI->n_audio; n++)
- if(AVI->audio[n]->audio_chunks) {
- AVI->audio[n]->audio_index = (audio_index_entry_t *) xine_xmalloc(nai[n] * sizeof(audio_index_entry_t));
- if(AVI->audio[n]->audio_index==0) ERR_EXIT(AVI_ERR_NO_MEM) ;
- }
-
- nvi = 0;
- memset((void *)nai,0,sizeof(long) * MAX_AUDIO_STREAMS);
- tot = 0;
+ AVI->audio_tot = 0;
ioff = idx_type == 1 ? 8 : AVI->movi_start+4;
for(i=0;i<AVI->n_idx;i++) {
if(strncasecmp(AVI->idx[i],AVI->video_tag,3) == 0) {
- AVI->video_index[nvi].pos = str2ulong(AVI->idx[i]+ 8)+ioff;
- AVI->video_index[nvi].len = str2ulong(AVI->idx[i]+12);
- AVI->video_index[nvi].flags = str2ulong(AVI->idx[i]+ 4);
- nvi++;
+ long pos = str2ulong(AVI->idx[i]+ 8)+ioff;
+ long len = str2ulong(AVI->idx[i]+12);
+ long flags = str2ulong(AVI->idx[i]+4);
+ if (video_index_append(AVI, pos, len, flags) == -1) {
+ ERR_EXIT(AVI_ERR_NO_MEM) ;
+ }
}
- for(n = 0; n < AVI->n_audio; n++)
+ for(n = 0; n < AVI->n_audio; n++) {
if(strncasecmp(AVI->idx[i],AVI->audio[n]->audio_tag,4) == 0) {
- AVI->audio[n]->audio_index[nai[n]].pos = str2ulong(AVI->idx[i]+ 8)+ioff;
- AVI->audio[n]->audio_index[nai[n]].len = str2ulong(AVI->idx[i]+12);
- AVI->audio[n]->audio_index[nai[n]].tot = tot;
- AVI->audio[n]->audio_bytes += AVI->audio[n]->audio_index[nai[n]].len;
- tot += AVI->audio[n]->audio_index[nai[n]].len;
- nai[n]++;
+ long pos = str2ulong(AVI->idx[i]+ 8)+ioff;
+ long len = str2ulong(AVI->idx[i]+12);
+ if (audio_index_append(AVI, n, pos, len, AVI->audio_tot) == -1) {
+ ERR_EXIT(AVI_ERR_NO_MEM) ;
+ }
+ AVI->audio_tot += len;
}
+ }
}
@@ -672,8 +834,9 @@ static long AVI_read_audio(demux_avi_t *this, avi_audio_t *AVI_A, char *audbuf,
long bytes, int *buf_flags) {
long nr, pos, left, todo;
+ audio_index_entry_t *aie = audio_cur_index_entry(this, AVI_A);
- if(!AVI_A->audio_index) {
+ if(!aie) {
this->AVI_errno = AVI_ERR_NO_IDX; return -1;
}
@@ -683,21 +846,26 @@ static long AVI_read_audio(demux_avi_t *this, avi_audio_t *AVI_A, char *audbuf,
while(bytes>0) {
- left = AVI_A->audio_index[AVI_A->audio_posc].len - AVI_A->audio_posb;
+ left = aie->len - AVI_A->audio_posb;
if(left==0) {
AVI_A->audio_posc++;
AVI_A->audio_posb = 0;
+ aie = audio_cur_index_entry(this, AVI_A);
+ if (!aie) {
+ this->AVI_errno = AVI_ERR_NO_IDX;
+ return -1;
+ }
if (nr>0) {
*buf_flags = BUF_FLAG_FRAME_END;
return nr;
}
- left = AVI_A->audio_index[AVI_A->audio_posc].len - AVI_A->audio_posb;
+ left = aie->len - AVI_A->audio_posb;
}
if(bytes<left)
todo = bytes;
else
todo = left;
- pos = AVI_A->audio_index[AVI_A->audio_posc].pos + AVI_A->audio_posb;
+ pos = aie->pos + AVI_A->audio_posb;
/* printf ("demux_avi: read audio from %d\n", pos); */
if (this->input->seek (this->input, pos, SEEK_SET)<0)
return -1;
@@ -711,7 +879,7 @@ static long AVI_read_audio(demux_avi_t *this, avi_audio_t *AVI_A, char *audbuf,
AVI_A->audio_posb += todo;
}
- left = AVI_A->audio_index[AVI_A->audio_posc].len - AVI_A->audio_posb;
+ left = aie->len - AVI_A->audio_posb;
if (left==0)
*buf_flags = BUF_FLAG_FRAME_END;
else
@@ -724,8 +892,9 @@ static long AVI_read_video(demux_avi_t *this, avi_t *AVI, char *vidbuf,
long bytes, int *buf_flags) {
long nr, pos, left, todo;
+ video_index_entry_t *vie = video_cur_index_entry(this);
- if (!AVI->video_index) {
+ if (!vie) {
this->AVI_errno = AVI_ERR_NO_IDX;
return -1;
}
@@ -734,22 +903,27 @@ static long AVI_read_video(demux_avi_t *this, avi_t *AVI, char *vidbuf,
while(bytes>0) {
- left = AVI->video_index[AVI->video_posf].len - AVI->video_posb;
+ left = vie->len - AVI->video_posb;
if(left==0) {
AVI->video_posf++;
AVI->video_posb = 0;
+ vie = video_cur_index_entry(this);
+ if (!vie) {
+ this->AVI_errno = AVI_ERR_NO_IDX;
+ return -1;
+ }
if (nr>0) {
*buf_flags = BUF_FLAG_FRAME_END;
return nr;
}
- left = AVI->video_index[AVI->video_posf].len - AVI->video_posb;
+ left = vie->len - AVI->video_posb;
}
if(bytes<left)
todo = bytes;
else
todo = left;
- pos = AVI->video_index[AVI->video_posf].pos + AVI->video_posb;
+ pos = vie->pos + AVI->video_posb;
/* printf ("demux_avi: read video from %d\n", pos); */
if (this->input->seek (this->input, pos, SEEK_SET)<0)
return -1;
@@ -763,7 +937,7 @@ static long AVI_read_video(demux_avi_t *this, avi_t *AVI, char *vidbuf,
AVI->video_posb += todo;
}
- left = AVI->video_index[AVI->video_posf].len - AVI->video_posb;
+ left = vie->len - AVI->video_posb;
if (left==0)
*buf_flags = BUF_FLAG_FRAME_END;
else
@@ -772,13 +946,14 @@ static long AVI_read_video(demux_avi_t *this, avi_t *AVI, char *vidbuf,
return nr;
}
-static int64_t get_audio_pts (demux_avi_t *this, int track, long posc, long posb) {
+static int64_t get_audio_pts (demux_avi_t *this, int track, long posc,
+ long postot, long posb) {
if (this->avi->audio[track]->dwSampleSize==0)
return posc * (double) this->avi->audio[track]->dwScale_audio /
this->avi->audio[track]->dwRate_audio * 90000.0;
else
- return (this->avi->audio[track]->audio_index[posc].tot+posb)/
+ return (postot+posb)/
this->avi->audio[track]->dwSampleSize * (double) this->avi->audio[track]->dwScale_audio /
this->avi->audio[track]->dwRate_audio * 90000.0;
}
@@ -795,11 +970,16 @@ static int demux_avi_next (demux_avi_t *this) {
int64_t audio_pts, video_pts;
int do_read_video = (this->avi->n_audio == 0);
- if (this->avi->video_frames <= this->avi->video_posf)
+ /* Try to grow the index, in case more of the avi file has shown up
+ * since we last checked. */
+ idx_grow(this);
+
+ /* If it's still too small, well then we're at the end. */
+ if (this->avi->video_idx.video_frames <= this->avi->video_posf)
return 0;
for (i=0; i < this->avi->n_audio; i++)
- if (!this->no_audio && (this->avi->audio[i]->audio_chunks <= this->avi->audio[i]->audio_posc))
+ if (!this->no_audio && (this->avi->audio[i]->audio_idx.audio_chunks <= this->avi->audio[i]->audio_posc))
return 0;
@@ -807,8 +987,14 @@ static int demux_avi_next (demux_avi_t *this) {
for (i=0; i < this->avi->n_audio; i++) {
avi_audio_t *audio = this->avi->audio[i];
+ audio_index_entry_t *aie = audio_cur_index_entry(this, audio);
- audio_pts = get_audio_pts (this, i, audio->audio_posc, audio->audio_posb);
+ /* The tests above mean aie should never be NULL, but just to be
+ * safe. */
+ if (!aie) return 0;
+
+ audio_pts =
+ get_audio_pts (this, i, audio->audio_posc, aie->tot, audio->audio_posb);
if (!this->no_audio && (audio_pts < video_pts)) {
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->content = buf->mem;
@@ -1010,6 +1196,7 @@ static void demux_avi_start (demux_plugin_t *this_gen,
uint32_t video_pts = 0;
int err;
unsigned char *sub;
+ video_index_entry_t *vie = NULL;
pthread_mutex_lock( &this->mutex );
@@ -1054,15 +1241,18 @@ static void demux_avi_start (demux_plugin_t *this_gen,
/* seek video */
if (start_pos) {
- while ( (this->avi->video_index[this->avi->video_posf].pos < start_pos)
- || !(this->avi->video_index[this->avi->video_posf].flags & AVIIF_KEYFRAME) ) {
- this->avi->video_posf++;
- if (this->avi->video_posf>this->avi->video_frames) {
+ while (1) {
+ vie = video_cur_index_entry(this);
+ if (vie && (vie->pos >= start_pos) && (vie->flags & AVIIF_KEYFRAME) ) {
+ break;
+ }
+ if (!vie) {
this->status = DEMUX_FINISHED;
printf ("demux_avi: video seek to start failed\n");
break;
}
+ this->avi->video_posf++;
}
video_pts = get_video_pts (this, this->avi->video_posf);
@@ -1071,15 +1261,19 @@ static void demux_avi_start (demux_plugin_t *this_gen,
video_pts = start_time * 90000;
- while ( (get_video_pts (this, this->avi->video_posf) < video_pts)
- || !(this->avi->video_index[this->avi->video_posf].flags & AVIIF_KEYFRAME) ) {
- this->avi->video_posf++;
- if (this->avi->video_posf>this->avi->video_frames) {
+ while (1) {
+ vie = video_cur_index_entry(this);
+ if (vie && (get_video_pts (this, this->avi->video_posf) >= video_pts)
+ && (vie->flags & AVIIF_KEYFRAME) ) {
+ break;
+ }
+ if (!vie) {
this->status = DEMUX_FINISHED;
printf ("demux_avi: video seek to start failed\n");
break;
}
+ this->avi->video_posf++;
}
video_pts = get_video_pts (this, this->avi->video_posf);
@@ -1089,14 +1283,21 @@ static void demux_avi_start (demux_plugin_t *this_gen,
/* seek audio */
if (!this->no_audio && this->status == DEMUX_OK) {
for(i=0; i < this->avi->n_audio; i++) {
- while (get_audio_pts (this, i, this->avi->audio[i]->audio_posc, 0) < video_pts) {
- this->avi->audio[i]->audio_posc++;
- if (this->avi->audio[i]->audio_posc>this->avi->audio[i]->audio_chunks) {
+ while (1) {
+ audio_index_entry_t *aie =
+ audio_cur_index_entry(this, this->avi->audio[i]);
+
+ if (aie && get_audio_pts(this, i, this->avi->audio[i]->audio_posc,
+ aie->tot, 0) >= video_pts) {
+ break;
+ }
+ if (!aie) {
this->status = DEMUX_FINISHED;
printf ("demux_avi: audio seek to start failed\n");
break;
}
+ this->avi->audio[i]->audio_posc++;
}
}
}
@@ -1250,7 +1451,7 @@ static int demux_avi_open(demux_plugin_t *this_gen,
if (this->avi) {
- printf ("demux_avi: %ld frames\n", this->avi->video_frames);
+ printf ("demux_avi: %ld frames\n", this->avi->video_idx.video_frames);
strncpy(this->last_mrl, input->get_mrl (input), 1024);
@@ -1326,7 +1527,7 @@ static int demux_avi_get_stream_length (demux_plugin_t *this_gen) {
demux_avi_t *this = (demux_avi_t *) this_gen;
if (this->avi) {
- return get_video_pts(this, this->avi->video_frames) / 90000 ;
+ return get_video_pts(this, this->avi->video_idx.video_frames) / 90000 ;
}
return 0;