* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
- #include "libavutil/intreadwrite.h"
- #include "libavutil/mathematics.h"
++#include "libavutil/avassert.h"
+ #include "libavutil/avstring.h"
#include "libavutil/bswap.h"
+#include "libavutil/opt.h"
#include "libavutil/dict.h"
- #include "libavutil/avstring.h"
- #include "libavutil/avassert.h"
+ #include "libavutil/intreadwrite.h"
+ #include "libavutil/mathematics.h"
#include "avformat.h"
- #include "internal.h"
#include "avi.h"
#include "dv.h"
+ #include "internal.h"
#include "riff.h"
-#undef NDEBUG
-#include <assert.h>
-
typedef struct AVIStream {
- int64_t frame_offset; /* current frame (video) or byte (audio) counter
- (used to compute the pts) */
+ int64_t frame_offset; /* current frame (video) or byte (audio) counter
+ * (used to compute the pts) */
int remaining;
int packet_size;
} AVIStream;
typedef struct {
- int64_t riff_end;
- int64_t movi_end;
- int64_t fsize;
+ const AVClass *class;
+ int64_t riff_end;
+ int64_t movi_end;
+ int64_t fsize;
+ int64_t io_fsize;
int64_t movi_list;
int64_t last_pkt_pos;
int index_loaded;
int is_odml;
int non_interleaved;
int stream_index;
- DVDemuxContext* dv_demux;
+ DVDemuxContext *dv_demux;
int odml_depth;
+ int use_odml;
#define MAX_ODML_DEPTH 1000
+ int64_t dts_max;
} AVIContext;
+
+static const AVOption options[] = {
+ { "use_odml", "use odml index", offsetof(AVIContext, use_odml), AV_OPT_TYPE_INT, {.i64 = 1}, -1, 1, AV_OPT_FLAG_DECODING_PARAM},
+ { NULL },
+};
+
+static const AVClass demuxer_class = {
+ .class_name = "avi",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+ .category = AV_CLASS_CATEGORY_DEMUXER,
+};
+
+
static const char avi_headers[][8] = {
- { 'R', 'I', 'F', 'F', 'A', 'V', 'I', ' ' },
- { 'R', 'I', 'F', 'F', 'A', 'V', 'I', 'X' },
- { 'R', 'I', 'F', 'F', 'A', 'V', 'I', 0x19},
- { 'O', 'N', '2', ' ', 'O', 'N', '2', 'f' },
- { 'R', 'I', 'F', 'F', 'A', 'M', 'V', ' ' },
+ { 'R', 'I', 'F', 'F', 'A', 'V', 'I', ' ' },
+ { 'R', 'I', 'F', 'F', 'A', 'V', 'I', 'X' },
+ { 'R', 'I', 'F', 'F', 'A', 'V', 'I', 0x19 },
+ { 'O', 'N', '2', ' ', 'O', 'N', '2', 'f' },
+ { 'R', 'I', 'F', 'F', 'A', 'M', 'V', ' ' },
{ 0 }
};
AVStream *st;
AVIStream *ast;
int i;
- int64_t last_pos= -1;
- int64_t filesize= avi->fsize;
-
- av_dlog(s, "longs_pre_entry:%d index_type:%d entries_in_use:%d chunk_id:%X base:%16"PRIX64"\n",
- longs_pre_entry,index_type, entries_in_use, chunk_id, base);
-
- if(stream_id >= s->nb_streams || stream_id < 0)
+ int64_t last_pos = -1;
- int64_t filesize = avio_size(s->pb);
++ int64_t filesize = avi->fsize;
+
+ av_dlog(s,
+ "longs_pre_entry:%d index_type:%d entries_in_use:%d "
+ "chunk_id:%X base:%16"PRIX64"\n",
+ longs_pre_entry,
+ index_type,
+ entries_in_use,
+ chunk_id,
+ base);
+
+ if (stream_id >= s->nb_streams || stream_id < 0)
return AVERROR_INVALIDDATA;
- st= s->streams[stream_id];
+ st = s->streams[stream_id];
ast = st->priv_data;
- if(index_sub_type)
+ if (index_sub_type)
return AVERROR_INVALIDDATA;
avio_rl32(pb);
return AVERROR_INVALIDDATA;
}
- for(i=0; i<entries_in_use; i++){
- if(index_type){
- int64_t pos= avio_rl32(pb) + base - 8;
- int len = avio_rl32(pb);
- int key= len >= 0;
+ for (i = 0; i < entries_in_use; i++) {
+ if (index_type) {
+ int64_t pos = avio_rl32(pb) + base - 8;
+ int len = avio_rl32(pb);
+ int key = len >= 0;
len &= 0x7FFFFFFF;
- av_dlog(s, "pos:%"PRId64", len:%X\n", pos, len);
-
- if (pb->eof_reached)
+#ifdef DEBUG_SEEK
+ av_log(s, AV_LOG_ERROR, "pos:%"PRId64", len:%X\n", pos, len);
+#endif
- if(url_feof(pb))
++ if (url_feof(pb))
return AVERROR_INVALIDDATA;
- if(last_pos == pos || pos == base - 8)
- avi->non_interleaved= 1;
- if(last_pos != pos && (len || !ast->sample_size))
- av_add_index_entry(st, pos, ast->cum_len, len, 0, key ? AVINDEX_KEYFRAME : 0);
+ if (last_pos == pos || pos == base - 8)
+ avi->non_interleaved = 1;
+ if (last_pos != pos && (len || !ast->sample_size))
+ av_add_index_entry(st, pos, ast->cum_len, len, 0,
+ key ? AVINDEX_KEYFRAME : 0);
ast->cum_len += get_duration(ast, len);
- last_pos= pos;
- }else{
+ last_pos = pos;
+ } else {
int64_t offset, pos;
int duration;
offset = avio_rl64(pb);
avio_rl32(pb); /* size */
duration = avio_rl32(pb);
- if(url_feof(pb))
- if (pb->eof_reached)
++ if (url_feof(pb))
return AVERROR_INVALIDDATA;
pos = avio_tell(pb);
return AVERROR_INVALIDDATA;
}
- if(avio_seek(pb, offset+8, SEEK_SET) < 0)
- avio_seek(pb, offset + 8, SEEK_SET);
++ if (avio_seek(pb, offset + 8, SEEK_SET) < 0)
+ return -1;
avi->odml_depth++;
read_braindead_odml_indx(s, frame_num);
avi->odml_depth--;
frame_num += duration;
- if(avio_seek(pb, pos, SEEK_SET) < 0) {
- avio_seek(pb, pos, SEEK_SET);
++ if (avio_seek(pb, pos, SEEK_SET) < 0) {
+ av_log(s, AV_LOG_ERROR, "Failed to restore position after reading index\n");
+ return -1;
+ }
+
}
}
- avi->index_loaded=2;
- avi->index_loaded = 1;
++ avi->index_loaded = 2;
return 0;
}
unsigned int size;
int i;
AVStream *st;
- AVIStream *ast = NULL;
- int avih_width=0, avih_height=0;
- int amv_file_format=0;
- uint64_t list_end = 0;
+ AVIStream *ast = NULL;
+ int avih_width = 0, avih_height = 0;
+ int amv_file_format = 0;
+ uint64_t list_end = 0;
int ret;
+ AVDictionaryEntry *dict_entry;
- avi->stream_index= -1;
+ avi->stream_index = -1;
ret = get_riff(s, pb);
if (ret < 0)
return ret;
- avi->fsize = avio_size(pb);
- if (avi->fsize <= 0)
+ av_log(avi, AV_LOG_DEBUG, "use odml:%d\n", avi->use_odml);
+
+ avi->io_fsize = avi->fsize = avio_size(pb);
- if(avi->fsize<=0 || avi->fsize < avi->riff_end)
- avi->fsize= avi->riff_end == 8 ? INT64_MAX : avi->riff_end;
++ if (avi->fsize <= 0 || avi->fsize < avi->riff_end)
+ avi->fsize = avi->riff_end == 8 ? INT64_MAX : avi->riff_end;
/* first list tag */
stream_index = -1;
- codec_type = -1;
+ codec_type = -1;
frame_period = 0;
- for(;;) {
+ for (;;) {
- if (pb->eof_reached)
+ if (url_feof(pb))
goto fail;
- tag = avio_rl32(pb);
+ tag = avio_rl32(pb);
size = avio_rl32(pb);
print_tag("tag", tag, size);
if (tag1 == MKTAG('m', 'o', 'v', 'i')) {
avi->movi_list = avio_tell(pb) - 4;
- if(size) avi->movi_end = avi->movi_list + size + (size & 1);
- else avi->movi_end = avi->fsize;
+ if (size)
+ avi->movi_end = avi->movi_list + size + (size & 1);
+ else
- avi->movi_end = avio_size(pb);
++ avi->movi_end = avi->fsize;
av_dlog(NULL, "movi end=%"PRIx64"\n", avi->movi_end);
goto end_of_header;
- }
- else if (tag1 == MKTAG('I', 'N', 'F', 'O'))
+ } else if (tag1 == MKTAG('I', 'N', 'F', 'O'))
ff_read_riff_info(s, size - 4);
else if (tag1 == MKTAG('n', 'c', 'd', 't'))
avi_read_nikon(s, list_end);
break;
}
- assert(stream_index < s->nb_streams);
+ av_assert0(stream_index < s->nb_streams);
- st->codec->stream_codec_tag= handler;
+ st->codec->stream_codec_tag = handler;
avio_rl32(pb); /* flags */
avio_rl16(pb); /* priority */
st->start_time = 0;
avio_rl32(pb); /* buffer size */
avio_rl32(pb); /* quality */
+ if (ast->cum_len*ast->scale/ast->rate > 3600) {
+ av_log(s, AV_LOG_ERROR, "crazy start time, iam scared, giving up\n");
+ return AVERROR_INVALIDDATA;
+ }
ast->sample_size = avio_rl32(pb); /* sample ssize */
- ast->cum_len *= FFMAX(1, ast->sample_size);
+ ast->cum_len *= FFMAX(1, ast->sample_size);
av_dlog(s, "%"PRIu32" %"PRIu32" %d\n",
ast->rate, ast->scale, ast->sample_size);
codec_type = AVMEDIA_TYPE_DATA;
break;
default:
- av_log(s, AV_LOG_ERROR, "unknown stream type %X\n", tag1);
- goto fail;
+ av_log(s, AV_LOG_INFO, "unknown stream type %X\n", tag1);
}
- if(ast->sample_size == 0) {
- if (ast->sample_size == 0)
++ if (ast->sample_size == 0) {
st->duration = st->nb_frames;
- ast->frame_offset= ast->cum_len;
+ if (st->duration > 0 && avi->io_fsize > 0 && avi->riff_end > avi->io_fsize) {
+ av_log(s, AV_LOG_DEBUG, "File is truncated adjusting duration\n");
+ st->duration = av_rescale(st->duration, avi->io_fsize, avi->riff_end);
+ }
+ }
+ ast->frame_offset = ast->cum_len;
avio_skip(pb, size - 12 * 4);
break;
case MKTAG('s', 't', 'r', 'f'):
avio_skip(pb, size);
break;
}
- tag1 = ff_get_bmp_header(pb, st);
+ tag1 = ff_get_bmp_header(pb, st, &esize);
- if (tag1 == MKTAG('D', 'X', 'S', 'B') || tag1 == MKTAG('D','X','S','A')) {
+ if (tag1 == MKTAG('D', 'X', 'S', 'B') ||
+ tag1 == MKTAG('D', 'X', 'S', 'A')) {
st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
- st->codec->codec_tag = tag1;
- st->codec->codec_id = AV_CODEC_ID_XSUB;
+ st->codec->codec_tag = tag1;
+ st->codec->codec_id = AV_CODEC_ID_XSUB;
break;
}
- if(size > 10*4 && size<(1<<30) && size < avi->fsize){
- if(esize == size-1 && (esize&1)) st->codec->extradata_size= esize - 10*4;
- else st->codec->extradata_size= size - 10*4;
- st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
- if (size > 10 * 4 && size < (1 << 30)) {
- st->codec->extradata_size = size - 10 * 4;
++ if (size > 10 * 4 && size < (1 << 30) && size < avi->fsize) {
++ if (esize == size-1 && (esize&1)) {
++ st->codec->extradata_size = esize - 10 * 4;
++ } else
++ st->codec->extradata_size = size - 10 * 4;
+ st->codec->extradata = av_malloc(st->codec->extradata_size +
+ FF_INPUT_BUFFER_PADDING_SIZE);
if (!st->codec->extradata) {
- st->codec->extradata_size= 0;
+ st->codec->extradata_size = 0;
return AVERROR(ENOMEM);
}
- avio_read(pb, st->codec->extradata, st->codec->extradata_size);
+ avio_read(pb,
+ st->codec->extradata,
+ st->codec->extradata_size);
}
- if(st->codec->extradata_size & 1) //FIXME check if the encoder really did this correctly
+ // FIXME: check if the encoder really did this correctly
+ if (st->codec->extradata_size & 1)
avio_r8(pb);
- /* Extract palette from extradata if bpp <= 8. */
- /* This code assumes that extradata contains only palette. */
- /* This is true for all paletted codecs implemented in FFmpeg. */
- if (st->codec->extradata_size && (st->codec->bits_per_coded_sample <= 8)) {
+ /* Extract palette from extradata if bpp <= 8.
+ * This code assumes that extradata contains only palette.
+ * This is true for all paletted codecs implemented in
- * Libav. */
++ * FFmpeg. */
+ if (st->codec->extradata_size &&
+ (st->codec->bits_per_coded_sample <= 8)) {
int pal_size = (1 << st->codec->bits_per_coded_sample) << 2;
const uint8_t *pal_src;
pal_size = FFMIN(pal_size, st->codec->extradata_size);
- pal_src = st->codec->extradata + st->codec->extradata_size - pal_size;
- for (i = 0; i < pal_size/4; i++)
+ pal_src = st->codec->extradata +
+ st->codec->extradata_size - pal_size;
-#if HAVE_BIGENDIAN
+ for (i = 0; i < pal_size / 4; i++)
- ast->pal[i] = av_bswap32(((uint32_t *)pal_src)[i]);
-#else
- memcpy(ast->pal, pal_src, pal_size);
-#endif
+ ast->pal[i] = 0xFFU<<24 | AV_RL32(pal_src+4*i);
ast->has_pal = 1;
}
print_tag("video", tag1, 0);
st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
- st->codec->codec_tag = tag1;
- st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag1);
- st->need_parsing = AVSTREAM_PARSE_HEADERS; // This is needed to get the pict type which is necessary for generating correct pts.
-
- if(st->codec->codec_tag==0 && st->codec->height > 0 && st->codec->extradata_size < 1U<<30){
- st->codec->extradata_size+= 9;
- st->codec->extradata= av_realloc_f(st->codec->extradata, 1, st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
- if(st->codec->extradata)
- memcpy(st->codec->extradata + st->codec->extradata_size - 9, "BottomUp", 9);
+ st->codec->codec_tag = tag1;
+ st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags,
+ tag1);
+ /* This is needed to get the pict type which is necessary
+ * for generating correct pts. */
+ st->need_parsing = AVSTREAM_PARSE_HEADERS;
- // Support "Resolution 1:1" for Avid AVI Codec
- if (tag1 == MKTAG('A', 'V', 'R', 'n') &&
- st->codec->extradata_size >= 31 &&
- !memcmp(&st->codec->extradata[28], "1:1", 3))
- st->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
+
+ if (st->codec->codec_tag == 0 && st->codec->height > 0 &&
+ st->codec->extradata_size < 1U << 30) {
+ st->codec->extradata_size += 9;
- st->codec->extradata = av_realloc(st->codec->extradata,
- st->codec->extradata_size +
- FF_INPUT_BUFFER_PADDING_SIZE);
++ st->codec->extradata = av_realloc_f(st->codec->extradata,
++ 1,
++ st->codec->extradata_size +
++ FF_INPUT_BUFFER_PADDING_SIZE);
+ if (st->codec->extradata)
+ memcpy(st->codec->extradata + st->codec->extradata_size - 9,
+ "BottomUp", 9);
}
- st->codec->height= FFABS(st->codec->height);
+ st->codec->height = FFABS(st->codec->height);
// avio_skip(pb, size - 5 * 4);
break;
st->need_parsing = AVSTREAM_PARSE_NONE;
/* AVI files with Xan DPCM audio (wrongly) declare PCM
* audio in the header but have Axan as stream_code_tag. */
- if (st->codec->stream_codec_tag == AV_RL32("Axan")){
+ if (st->codec->stream_codec_tag == AV_RL32("Axan")) {
st->codec->codec_id = AV_CODEC_ID_XAN_DPCM;
st->codec->codec_tag = 0;
+ ast->dshow_block_align = 0;
}
- if (amv_file_format){
- st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_AMV;
+ if (amv_file_format) {
+ st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_AMV;
ast->dshow_block_align = 0;
}
- if(st->codec->codec_id == AV_CODEC_ID_AAC && ast->dshow_block_align <= 4 && ast->dshow_block_align) {
++ if (st->codec->codec_id == AV_CODEC_ID_AAC && ast->dshow_block_align <= 4 && ast->dshow_block_align) {
+ av_log(s, AV_LOG_DEBUG, "overriding invalid dshow_block_align of %d\n", ast->dshow_block_align);
+ ast->dshow_block_align = 0;
+ }
- if(st->codec->codec_id == AV_CODEC_ID_AAC && ast->dshow_block_align == 1024 && ast->sample_size == 1024 ||
++ if (st->codec->codec_id == AV_CODEC_ID_AAC && ast->dshow_block_align == 1024 && ast->sample_size == 1024 ||
+ st->codec->codec_id == AV_CODEC_ID_AAC && ast->dshow_block_align == 4096 && ast->sample_size == 4096 ||
+ st->codec->codec_id == AV_CODEC_ID_MP3 && ast->dshow_block_align == 1152 && ast->sample_size == 1152) {
+ av_log(s, AV_LOG_DEBUG, "overriding sample_size\n");
+ ast->sample_size = 0;
+ }
break;
case AVMEDIA_TYPE_SUBTITLE:
st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
}
}
break;
- if(size<(1<<30)){
+ case MKTAG('s', 't', 'r', 'd'):
+ if (stream_index >= (unsigned)s->nb_streams
+ || s->streams[stream_index]->codec->extradata_size
+ || s->streams[stream_index]->codec->codec_tag == MKTAG('H','2','6','4')) {
+ avio_skip(pb, size);
+ } else {
+ uint64_t cur_pos = avio_tell(pb);
+ if (cur_pos < list_end)
+ size = FFMIN(size, list_end - cur_pos);
+ st = s->streams[stream_index];
+
- if(st->codec->extradata_size & 1) //FIXME check if the encoder really did this correctly
++ if (size<(1<<30)) {
+ st->codec->extradata_size= size;
+ st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ if (!st->codec->extradata) {
+ st->codec->extradata_size= 0;
+ return AVERROR(ENOMEM);
+ }
+ avio_read(pb, st->codec->extradata, st->codec->extradata_size);
+ }
+
++ if (st->codec->extradata_size & 1) //FIXME check if the encoder really did this correctly
+ avio_r8(pb);
+ }
+ break;
case MKTAG('i', 'n', 'd', 'x'):
- i= avio_tell(pb);
- if(pb->seekable && !(s->flags & AVFMT_FLAG_IGNIDX) && avi->use_odml &&
- read_braindead_odml_indx(s, 0) < 0 && (s->error_recognition & AV_EF_EXPLODE))
+ i = avio_tell(pb);
+ if (pb->seekable && !(s->flags & AVFMT_FLAG_IGNIDX) &&
++ avi->use_odml &&
+ read_braindead_odml_indx(s, 0) < 0 &&
+ (s->error_recognition & AV_EF_EXPLODE))
goto fail;
- avio_seek(pb, i+size, SEEK_SET);
+ avio_seek(pb, i + size, SEEK_SET);
break;
case MKTAG('v', 'p', 'r', 'p'):
- if(stream_index < (unsigned)s->nb_streams && size > 9*4){
+ if (stream_index < (unsigned)s->nb_streams && size > 9 * 4) {
AVRational active, active_aspect;
st = s->streams[stream_index];
return AVERROR_INVALIDDATA;
}
- if(!avi->index_loaded && pb->seekable)
+ if (!avi->index_loaded && pb->seekable)
avi_load_index(s);
- avi->index_loaded |= 1;
- avi->index_loaded = 1;
- avi->non_interleaved |= guess_ni_flag(s);
++ avi->index_loaded |= 1;
+ avi->non_interleaved |= guess_ni_flag(s) | (s->flags & AVFMT_FLAG_SORT_DTS);
+
+ dict_entry = av_dict_get(s->metadata, "ISFT", NULL, 0);
+ if (dict_entry && !strcmp(dict_entry->value, "PotEncoder"))
- for (i=0; i<s->nb_streams; i++) {
++ for (i = 0; i < s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+ if ( st->codec->codec_id == AV_CODEC_ID_MPEG1VIDEO
+ || st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO)
+ st->need_parsing = AVSTREAM_PARSE_FULL;
+ }
+
- for(i=0; i<s->nb_streams; i++){
+ for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
- if(st->nb_index_entries)
+ if (st->nb_index_entries)
break;
}
- if(avi->dv_demux)
- avi->non_interleaved=0;
- if(i==s->nb_streams && avi->non_interleaved) {
- av_log(s, AV_LOG_WARNING, "non-interleaved AVI without index, switching to interleaved\n");
- avi->non_interleaved=0;
+ // DV-in-AVI cannot be non-interleaved, if set this must be
+ // a mis-detection.
++ if (avi->dv_demux)
++ avi->non_interleaved = 0;
+ if (i == s->nb_streams && avi->non_interleaved) {
+ av_log(s, AV_LOG_WARNING,
+ "Non-interleaved AVI without index, switching to interleaved\n");
+ avi->non_interleaved = 0;
}
- if(avi->non_interleaved) {
+ if (avi->non_interleaved) {
av_log(s, AV_LOG_INFO, "non-interleaved AVI\n");
clean_index(s);
}
return 0;
}
- static int read_gab2_sub(AVStream *st, AVPacket *pkt) {
- if (pkt->data && !strcmp(pkt->data, "GAB2") && AV_RL16(pkt->data+5) == 2) {
+ static int read_gab2_sub(AVStream *st, AVPacket *pkt)
+ {
- if (!strcmp(pkt->data, "GAB2") && AV_RL16(pkt->data + 5) == 2) {
++ if (pkt->data && !strcmp(pkt->data, "GAB2") && AV_RL16(pkt->data + 5) == 2) {
uint8_t desc[256];
- int score = AVPROBE_SCORE_EXTENSION, ret;
+ int score = AVPROBE_SCORE_EXTENSION, ret;
AVIStream *ast = st->priv_data;
AVInputFormat *sub_demuxer;
AVRational time_base;
start_sync:
memset(d, -1, sizeof(d));
- for(i=sync=avio_tell(pb); !url_feof(pb); i++) {
- for (i = sync = avio_tell(pb); !pb->eof_reached; i++) {
++ for (i = sync = avio_tell(pb); !url_feof(pb); i++) {
int j;
- for(j=0; j<7; j++)
- d[j]= d[j+1];
- d[7]= avio_r8(pb);
+ for (j = 0; j < 7; j++)
+ d[j] = d[j + 1];
+ d[7] = avio_r8(pb);
- size= d[4] + (d[5]<<8) + (d[6]<<16) + (d[7]<<24);
+ size = d[4] + (d[5] << 8) + (d[6] << 16) + (d[7] << 24);
- n= get_stream_idx(d+2);
+ n = get_stream_idx(d + 2);
av_dlog(s, "%X %X %X %X %X %X %X %X %"PRId64" %u %d\n",
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], i, size, n);
- if(i*(avi->io_fsize>0) + (uint64_t)size > avi->fsize || d[0] > 127)
- if (i + (uint64_t)size > avi->fsize || d[0] > 127)
++ if (i*(avi->io_fsize>0) + (uint64_t)size > avi->fsize || d[0] > 127)
continue;
- //parse ix##
- if( (d[0] == 'i' && d[1] == 'x' && n < s->nb_streams)
- //parse JUNK
- ||(d[0] == 'J' && d[1] == 'U' && d[2] == 'N' && d[3] == 'K')
- ||(d[0] == 'i' && d[1] == 'd' && d[2] == 'x' && d[3] == '1')){
+ // parse ix##
+ if ((d[0] == 'i' && d[1] == 'x' && n < s->nb_streams) ||
+ // parse JUNK
+ (d[0] == 'J' && d[1] == 'U' && d[2] == 'N' && d[3] == 'K') ||
+ (d[0] == 'i' && d[1] == 'd' && d[2] == 'x' && d[3] == '1')) {
avio_skip(pb, size);
goto start_sync;
}
goto start_sync;
}
- //parse ##dc/##wb
- if(n < s->nb_streams){
+ // parse ##dc/##wb
+ if (n < s->nb_streams) {
AVStream *st;
AVIStream *ast;
- st = s->streams[n];
+ st = s->streams[n];
ast = st->priv_data;
- if(s->nb_streams>=2){
- AVStream *st1 = s->streams[1];
- AVIStream *ast1= st1->priv_data;
- //workaround for broken small-file-bug402.avi
- if( d[2] == 'w' && d[3] == 'b'
- && n==0
+ if (!ast) {
+ av_log(s, AV_LOG_WARNING, "Skiping foreign stream %d packet\n", n);
+ continue;
+ }
+
- if (d[2] == 'w' && d[3] == 'b' && n == 0 &&
- st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
- st1->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
- ast->prefix == 'd' * 256 + 'c' &&
- (d[2] * 256 + d[3] == ast1->prefix ||
- !ast1->prefix_count)) {
+ if (s->nb_streams >= 2) {
+ AVStream *st1 = s->streams[1];
+ AVIStream *ast1 = st1->priv_data;
+ // workaround for broken small-file-bug402.avi
- ){
- n=1;
- st = st1;
++ if ( d[2] == 'w' && d[3] == 'b'
++ && n == 0
+ && st ->codec->codec_type == AVMEDIA_TYPE_VIDEO
+ && st1->codec->codec_type == AVMEDIA_TYPE_AUDIO
+ && ast->prefix == 'd'*256+'c'
+ && (d[2]*256+d[3] == ast1->prefix || !ast1->prefix_count)
++ ) {
+ n = 1;
+ st = st1;
ast = ast1;
- av_log(s, AV_LOG_WARNING, "Invalid stream + prefix combination, assuming audio.\n");
+ av_log(s, AV_LOG_WARNING,
+ "Invalid stream + prefix combination, assuming audio.\n");
}
}
-
- if( (st->discard >= AVDISCARD_DEFAULT && size==0)
- /*|| (st->discard >= AVDISCARD_NONKEY && !(pkt->flags & AV_PKT_FLAG_KEY))*/ //FIXME needs a little reordering
- || st->discard >= AVDISCARD_ALL){
+ if ((st->discard >= AVDISCARD_DEFAULT && size == 0)
+ /* || (st->discard >= AVDISCARD_NONKEY && !(pkt->flags & AV_PKT_FLAG_KEY)) */ // FIXME: needs a little reordering
+ || st->discard >= AVDISCARD_ALL) {
if (!exit_early) {
ast->frame_offset += get_duration(ast, size);
+ avio_skip(pb, size);
+ goto start_sync;
}
- avio_skip(pb, size);
- goto start_sync;
}
- if (d[2] == 'p' && d[3] == 'c' && size<=4*256+4) {
- int k = avio_r8(pb);
+ if (d[2] == 'p' && d[3] == 'c' && size <= 4 * 256 + 4) {
+ int k = avio_r8(pb);
int last = (k + avio_r8(pb) - 1) & 0xFF;
- avio_rl16(pb); //flags
+ avio_rl16(pb); // flags
+ // b + (g << 8) + (r << 16);
for (; k <= last; k++)
- ast->pal[k] = 0xFFU<<24 | avio_rb32(pb)>>8;// b + (g << 8) + (r << 16);
- ast->has_pal= 1;
- goto start_sync;
- } else if( ((ast->prefix_count<5 || sync+9 > i) && d[2]<128 && d[3]<128) ||
- d[2]*256+d[3] == ast->prefix /*||
- (d[2] == 'd' && d[3] == 'c') ||
- (d[2] == 'w' && d[3] == 'b')*/) {
- ast->pal[k] = avio_rb32(pb) >> 8;
++ ast->pal[k] = 0xFFU<<24 | avio_rb32(pb)>>8;
+ ast->has_pal = 1;
+ goto start_sync;
+ } else if (((ast->prefix_count < 5 || sync + 9 > i) &&
+ d[2] < 128 && d[3] < 128) ||
+ d[2] * 256 + d[3] == ast->prefix /* ||
+ (d[2] == 'd' && d[3] == 'c') ||
+ (d[2] == 'w' && d[3] == 'b') */) {
if (exit_early)
return 0;
- if(d[2]*256+d[3] == ast->prefix)
+ if (d[2] * 256 + d[3] == ast->prefix)
ast->prefix_count++;
- else{
- ast->prefix= d[2]*256+d[3];
- ast->prefix_count= 0;
+ else {
+ ast->prefix = d[2] * 256 + d[3];
+ ast->prefix_count = 0;
}
- avi->stream_index= n;
- ast->packet_size= size + 8;
- ast->remaining= size;
+ avi->stream_index = n;
+ ast->packet_size = size + 8;
+ ast->remaining = size;
- if(size || !ast->sample_size){
- uint64_t pos= avio_tell(pb) - 8;
- if(!st->index_entries || !st->nb_index_entries || st->index_entries[st->nb_index_entries - 1].pos < pos){
- av_add_index_entry(st, pos, ast->frame_offset, size, 0, AVINDEX_KEYFRAME);
+ if (size || !ast->sample_size) {
+ uint64_t pos = avio_tell(pb) - 8;
+ if (!st->index_entries || !st->nb_index_entries ||
+ st->index_entries[st->nb_index_entries - 1].pos < pos) {
+ av_add_index_entry(st, pos, ast->frame_offset, size,
+ 0, AVINDEX_KEYFRAME);
}
}
return 0;
}
}
- if(pb->error)
++ if (pb->error)
+ return pb->error;
return AVERROR_EOF;
}
return AVERROR_EOF;
best_ast = best_st->priv_data;
- best_ts = best_ast->frame_offset;
- if(best_ast->remaining)
- i= av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
- else{
- i= av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY);
- if(i>=0)
- best_ast->frame_offset= best_st->index_entries[i].timestamp;
- best_ts = av_rescale_q(best_ts,
- (AVRational) { FFMAX(1, best_ast->sample_size),
- AV_TIME_BASE },
- best_st->time_base);
++ best_ts = best_ast->frame_offset;
+ if (best_ast->remaining) {
+ i = av_index_search_timestamp(best_st,
+ best_ts,
+ AVSEEK_FLAG_ANY |
+ AVSEEK_FLAG_BACKWARD);
+ } else {
+ i = av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY);
+ if (i >= 0)
+ best_ast->frame_offset = best_st->index_entries[i].timestamp;
}
- if(i>=0){
- int64_t pos= best_st->index_entries[i].pos;
+ if (i >= 0) {
+ int64_t pos = best_st->index_entries[i].pos;
pos += best_ast->packet_size - best_ast->remaining;
- if(avio_seek(s->pb, pos + 8, SEEK_SET) < 0)
- avio_seek(s->pb, pos + 8, SEEK_SET);
++ if (avio_seek(s->pb, pos + 8, SEEK_SET) < 0)
+ return AVERROR_EOF;
- assert(best_ast->remaining <= best_ast->packet_size);
+ av_assert0(best_ast->remaining <= best_ast->packet_size);
- avi->stream_index= best_stream_index;
- if(!best_ast->remaining)
- best_ast->packet_size=
- best_ast->remaining= best_st->index_entries[i].size;
+ avi->stream_index = best_stream_index;
+ if (!best_ast->remaining)
+ best_ast->packet_size =
+ best_ast->remaining = best_st->index_entries[i].size;
}
+ else
+ return AVERROR_EOF;
}
resync:
- if(avi->stream_index >= 0){
- AVStream *st= s->streams[ avi->stream_index ];
- AVIStream *ast= st->priv_data;
+ if (avi->stream_index >= 0) {
+ AVStream *st = s->streams[avi->stream_index];
+ AVIStream *ast = st->priv_data;
int size, err;
- if(get_subtitle_pkt(s, st, pkt))
+ if (get_subtitle_pkt(s, st, pkt))
return 0;
- if(ast->sample_size <= 1) // minorityreport.AVI block_align=1024 sample_size=1 IMA-ADPCM
- size= INT_MAX;
- else if(ast->sample_size < 32)
+ // minorityreport.AVI block_align=1024 sample_size=1 IMA-ADPCM
+ if (ast->sample_size <= 1)
+ size = INT_MAX;
+ else if (ast->sample_size < 32)
// arbitrary multiplier to avoid tiny packets for raw PCM data
- size= 1024*ast->sample_size;
+ size = 1024 * ast->sample_size;
else
- size= ast->sample_size;
+ size = ast->sample_size;
- if(size > ast->remaining)
- size= ast->remaining;
- avi->last_pkt_pos= avio_tell(pb);
- err= av_get_packet(pb, pkt, size);
- if(err<0)
+ if (size > ast->remaining)
+ size = ast->remaining;
+ avi->last_pkt_pos = avio_tell(pb);
+ err = av_get_packet(pb, pkt, size);
+ if (err < 0)
return err;
+ size = err;
- if(ast->has_pal && pkt->size<(unsigned)INT_MAX/2){
- if (ast->has_pal && pkt->data && pkt->size < (unsigned)INT_MAX / 2) {
++ if (ast->has_pal && pkt->size < (unsigned)INT_MAX / 2) {
uint8_t *pal;
- pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
- if(!pal){
- av_log(s, AV_LOG_ERROR, "Failed to allocate data for palette\n");
- }else{
+ pal = av_packet_new_side_data(pkt,
+ AV_PKT_DATA_PALETTE,
+ AVPALETTE_SIZE);
+ if (!pal) {
+ av_log(s, AV_LOG_ERROR,
+ "Failed to allocate data for palette\n");
+ } else {
memcpy(pal, ast->pal, AVPALETTE_SIZE);
ast->has_pal = 0;
}
dstr = pkt->destruct;
#endif
size = avpriv_dv_produce_packet(avi->dv_demux, pkt,
- pkt->data, pkt->size, pkt->pos);
- pkt->data, pkt->size);
++ pkt->data, pkt->size, pkt->pos);
#if FF_API_DESTRUCT_PACKET
pkt->destruct = dstr;
#endif
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
AVIndexEntry *e;
int index;
- assert(st->index_entries);
+ av_assert0(st->index_entries);
- index= av_index_search_timestamp(st, ast->frame_offset, 0);
- e= &st->index_entries[index];
+ index = av_index_search_timestamp(st, ast->frame_offset, 0);
+ e = &st->index_entries[index];
- if(index >= 0 && e->timestamp == ast->frame_offset){
- if (index == st->nb_index_entries-1){
- if (index >= 0 && e->timestamp == ast->frame_offset)
++ if (index >= 0 && e->timestamp == ast->frame_offset) {
++ if (index == st->nb_index_entries-1) {
+ int key=1;
+ int i;
+ uint32_t state=-1;
- for(i=0; i<FFMIN(size,256); i++){
- if(st->codec->codec_id == AV_CODEC_ID_MPEG4){
- if(state == 0x1B6){
++ for (i=0; i<FFMIN(size,256); i++) {
++ if (st->codec->codec_id == AV_CODEC_ID_MPEG4) {
++ if (state == 0x1B6) {
+ key= !(pkt->data[i]&0xC0);
+ break;
+ }
+ }else
+ break;
+ state= (state<<8) + pkt->data[i];
+ }
- if(!key)
++ if (!key)
+ e->flags &= ~AVINDEX_KEYFRAME;
+ }
if (e->flags & AVINDEX_KEYFRAME)
pkt->flags |= AV_PKT_FLAG_KEY;
+ }
} else {
pkt->flags |= AV_PKT_FLAG_KEY;
}
ast->frame_offset += get_duration(ast, pkt->size);
}
ast->remaining -= err;
- if(!ast->remaining){
- avi->stream_index= -1;
- ast->packet_size= 0;
+ if (!ast->remaining) {
+ avi->stream_index = -1;
+ ast->packet_size = 0;
}
- if(!avi->non_interleaved && pkt->pos >= 0 && ast->seek_pos > pkt->pos){
++ if (!avi->non_interleaved && pkt->pos >= 0 && ast->seek_pos > pkt->pos) {
+ av_free_packet(pkt);
+ goto resync;
+ }
+ ast->seek_pos= 0;
+
- if(!avi->non_interleaved && st->nb_index_entries>1 && avi->index_loaded>1){
++ if (!avi->non_interleaved && st->nb_index_entries>1 && avi->index_loaded>1) {
+ int64_t dts= av_rescale_q(pkt->dts, st->time_base, AV_TIME_BASE_Q);
+
- if(avi->dts_max - dts > 2*AV_TIME_BASE){
++ if (avi->dts_max - dts > 2*AV_TIME_BASE) {
+ avi->non_interleaved= 1;
+ av_log(s, AV_LOG_INFO, "Switching to NI mode, due to poor interleaving\n");
- }else if(avi->dts_max < dts)
++ }else if (avi->dts_max < dts)
+ avi->dts_max = dts;
+ }
+
return 0;
}
AVStream *st;
AVIStream *ast;
unsigned int index, tag, flags, pos, len, first_packet = 1;
- unsigned last_pos= -1;
- unsigned last_idx= -1;
+ unsigned last_pos = -1;
++ unsigned last_idx = -1;
int64_t idx1_pos, first_packet_pos = 0, data_offset = 0;
+ int anykey = 0;
nb_index_entries = size / 16;
if (nb_index_entries <= 0)
avi->stream_index = -1;
avio_seek(pb, idx1_pos, SEEK_SET);
- if (s->nb_streams == 1 && s->streams[0]->codec->codec_tag == AV_RL32("MMES")){
++ if (s->nb_streams == 1 && s->streams[0]->codec->codec_tag == AV_RL32("MMES")) {
+ first_packet_pos = 0;
+ data_offset = avi->movi_list;
+ }
+
/* Read the entries and sort them in each stream component. */
- for(i = 0; i < nb_index_entries; i++) {
- if(url_feof(pb))
+ for (i = 0; i < nb_index_entries; i++) {
++ if (url_feof(pb))
+ return -1;
+
- tag = avio_rl32(pb);
+ tag = avio_rl32(pb);
flags = avio_rl32(pb);
- pos = avio_rl32(pb);
- len = avio_rl32(pb);
+ pos = avio_rl32(pb);
+ len = avio_rl32(pb);
av_dlog(s, "%d: tag=0x%x flags=0x%x pos=0x%x len=%d/",
i, tag, flags, pos, len);
av_dlog(s, "%d cum_len=%"PRId64"\n", len, ast->cum_len);
- if (pb->eof_reached)
- return AVERROR_INVALIDDATA;
-
+ // even if we have only a single stream, we should
+ // switch to non-interleaved to get correct timestamps
- if(last_pos == pos)
- avi->non_interleaved= 1;
- if(last_idx != pos && len) {
- av_add_index_entry(st, pos, ast->cum_len, len, 0, (flags&AVIIF_INDEX) ? AVINDEX_KEYFRAME : 0);
+ if (last_pos == pos)
+ avi->non_interleaved = 1;
- else if (len || !ast->sample_size)
++ if (last_idx != pos && len) {
+ av_add_index_entry(st, pos, ast->cum_len, len, 0,
+ (flags & AVIIF_INDEX) ? AVINDEX_KEYFRAME : 0);
+ last_idx= pos;
+ }
ast->cum_len += get_duration(ast, len);
- last_pos= pos;
- anykey |= flags&AVIIF_INDEX;
+ last_pos = pos;
++ anykey |= flags&AVIIF_INDEX;
+ }
+ if (!anykey) {
+ for (index = 0; index < s->nb_streams; index++) {
+ st = s->streams[index];
+ if (st->nb_index_entries)
+ st->index_entries[0].flags |= AVINDEX_KEYFRAME;
+ }
}
return 0;
}
- static int guess_ni_flag(AVFormatContext *s){
+ static int guess_ni_flag(AVFormatContext *s)
+ {
int i;
- int64_t last_start=0;
- int64_t first_end= INT64_MAX;
- int64_t oldpos= avio_tell(s->pb);
+ int64_t last_start = 0;
+ int64_t first_end = INT64_MAX;
+ int64_t oldpos = avio_tell(s->pb);
+ int *idx;
+ int64_t min_pos, pos;
- for(i=0; i<s->nb_streams; i++){
+ for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i];
- int n= st->nb_index_entries;
+ int n = st->nb_index_entries;
unsigned int size;
- if(n <= 0)
+ if (n <= 0)
continue;
- if(n >= 2){
- int64_t pos= st->index_entries[0].pos;
+ if (n >= 2) {
+ int64_t pos = st->index_entries[0].pos;
avio_seek(s->pb, pos + 4, SEEK_SET);
- size= avio_rl32(s->pb);
- if(pos + size > st->index_entries[1].pos)
- last_start= INT64_MAX;
+ size = avio_rl32(s->pb);
+ if (pos + size > st->index_entries[1].pos)
+ last_start = INT64_MAX;
}
- if(st->index_entries[0].pos > last_start)
- last_start= st->index_entries[0].pos;
- if(st->index_entries[n-1].pos < first_end)
- first_end= st->index_entries[n-1].pos;
+ if (st->index_entries[0].pos > last_start)
+ last_start = st->index_entries[0].pos;
+ if (st->index_entries[n - 1].pos < first_end)
+ first_end = st->index_entries[n - 1].pos;
}
avio_seek(s->pb, oldpos, SEEK_SET);
- return last_start > first_end;
+ if (last_start > first_end)
+ return 1;
+ idx= av_mallocz(sizeof(*idx) * s->nb_streams);
+ for (min_pos=pos=0; min_pos!=INT64_MAX; pos= min_pos+1LU) {
+ int64_t max_dts = INT64_MIN/2, min_dts= INT64_MAX/2;
+ min_pos = INT64_MAX;
+
+ for (i=0; i<s->nb_streams; i++) {
+ AVStream *st = s->streams[i];
+ AVIStream *ast = st->priv_data;
+ int n= st->nb_index_entries;
+ while (idx[i]<n && st->index_entries[idx[i]].pos < pos)
+ idx[i]++;
+ if (idx[i] < n) {
+ min_dts = FFMIN(min_dts, av_rescale_q(st->index_entries[idx[i]].timestamp/FFMAX(ast->sample_size, 1), st->time_base, AV_TIME_BASE_Q));
+ min_pos = FFMIN(min_pos, st->index_entries[idx[i]].pos);
+ }
+ if (idx[i])
+ max_dts = FFMAX(max_dts, av_rescale_q(st->index_entries[idx[i]-1].timestamp/FFMAX(ast->sample_size, 1), st->time_base, AV_TIME_BASE_Q));
+ }
- if(max_dts - min_dts > 2*AV_TIME_BASE) {
++ if (max_dts - min_dts > 2*AV_TIME_BASE) {
+ av_free(idx);
+ return 1;
+ }
+ }
+ av_free(idx);
+ return 0;
}
static int avi_load_index(AVFormatContext *s)
AVIContext *avi = s->priv_data;
AVIOContext *pb = s->pb;
uint32_t tag, size;
- int64_t pos= avio_tell(pb);
+ int64_t pos = avio_tell(pb);
+ int64_t next;
- int ret = -1;
+ int ret = -1;
if (avio_seek(pb, avi->movi_end, SEEK_SET) < 0)
goto the_end; // maybe truncated file
av_dlog(s, "movi_end=0x%"PRIx64"\n", avi->movi_end);
- for(;;) {
- tag = avio_rl32(pb);
+ for (;;) {
- if (pb->eof_reached)
- break;
+ tag = avio_rl32(pb);
size = avio_rl32(pb);
+ if (url_feof(pb))
+ break;
+ next = avio_tell(pb) + size + (size & 1);
+
av_dlog(s, "tag=%c%c%c%c size=0x%x\n",
tag & 0xff,
(tag >> 8) & 0xff,
if (tag == MKTAG('i', 'd', 'x', '1') &&
avi_read_idx1(s, size) >= 0) {
+ avi->index_loaded=2;
ret = 0;
- }else if(tag == MKTAG('L', 'I', 'S', 'T')) {
++ }else if (tag == MKTAG('L', 'I', 'S', 'T')) {
+ uint32_t tag1 = avio_rl32(pb);
+
+ if (tag1 == MKTAG('I', 'N', 'F', 'O'))
+ ff_read_riff_info(s, size - 4);
- }else if(!ret)
++ }else if (!ret)
break;
- }
- size += (size & 1);
- if (avio_skip(pb, size) < 0)
+ if (avio_seek(pb, next, SEEK_SET) < 0)
break; // something is wrong here
}
- the_end:
+
+ the_end:
avio_seek(pb, pos, SEEK_SET);
return ret;
}
if (!avi->index_loaded) {
/* we only load the index on demand */
avi_load_index(s);
- avi->index_loaded = 1;
+ avi->index_loaded |= 1;
}
- av_assert0(stream_index>= 0);
-
- st = s->streams[stream_index];
- ast= st->priv_data;
- index= av_index_search_timestamp(st, timestamp * FFMAX(ast->sample_size, 1), flags);
- if (index<0) {
- assert(stream_index >= 0);
++ av_assert0(stream_index >= 0);
+
+ st = s->streams[stream_index];
+ ast = st->priv_data;
+ index = av_index_search_timestamp(st,
+ timestamp * FFMAX(ast->sample_size, 1),
+ flags);
- if (index < 0)
++ if (index < 0) {
+ if (st->nb_index_entries > 0)
+ av_log(s, AV_LOG_DEBUG, "Failed to find timestamp %"PRId64 " in index %"PRId64 " .. %"PRId64 "\n",
+ timestamp * FFMAX(ast->sample_size, 1),
+ st->index_entries[0].timestamp,
+ st->index_entries[st->nb_index_entries - 1].timestamp);
return AVERROR_INVALIDDATA;
+ }
/* find the position */
- pos = st->index_entries[index].pos;
+ pos = st->index_entries[index].pos;
timestamp = st->index_entries[index].timestamp / FFMAX(ast->sample_size, 1);
av_dlog(s, "XX %"PRId64" %d %"PRId64"\n",
/* One and only one real stream for DV in AVI, and it has video */
/* offsets. Calling with other stream indexes should have failed */
/* the av_index_search_timestamp call above. */
- assert(stream_index == 0);
+ av_assert0(stream_index == 0);
+
- if(avio_seek(s->pb, pos, SEEK_SET) < 0)
++ if (avio_seek(s->pb, pos, SEEK_SET) < 0)
+ return -1;
/* Feed the DV video stream version of the timestamp to the */
/* DV demux so it can synthesize correct timestamps. */
ff_dv_offset_reset(avi->dv_demux, timestamp);
- avi->stream_index= -1;
- avio_seek(s->pb, pos, SEEK_SET);
+ avi->stream_index = -1;
return 0;
}
- pos_min= pos;
- for(i = 0; i < s->nb_streams; i++) {
- AVStream *st2 = s->streams[i];
++ pos_min = pos;
+ for (i = 0; i < s->nb_streams; i++) {
+ AVStream *st2 = s->streams[i];
AVIStream *ast2 = st2->priv_data;
- ast2->packet_size=
- ast2->remaining= 0;
+ ast2->packet_size =
+ ast2->remaining = 0;
if (ast2->sub_ctx) {
seek_subtitle(st, st2, timestamp);
if (st2->nb_index_entries <= 0)
continue;
-// assert(st2->codec->block_align);
- assert((int64_t)st2->time_base.num * ast2->rate ==
- (int64_t)st2->time_base.den * ast2->scale);
+// av_assert1(st2->codec->block_align);
- av_assert0((int64_t)st2->time_base.num*ast2->rate == (int64_t)st2->time_base.den*ast2->scale);
- index = av_index_search_timestamp(
- st2,
- av_rescale_q(timestamp, st->time_base, st2->time_base) * FFMAX(ast2->sample_size, 1),
- flags | AVSEEK_FLAG_BACKWARD | (st2->codec->codec_type != AVMEDIA_TYPE_VIDEO ? AVSEEK_FLAG_ANY : 0));
- if(index<0)
- index=0;
- ast2->seek_pos= st2->index_entries[index].pos;
- pos_min= FFMIN(pos_min,ast2->seek_pos);
++ av_assert0((int64_t)st2->time_base.num * ast2->rate ==
++ (int64_t)st2->time_base.den * ast2->scale);
+ index = av_index_search_timestamp(st2,
+ av_rescale_q(timestamp,
+ st->time_base,
+ st2->time_base) *
+ FFMAX(ast2->sample_size, 1),
- flags | AVSEEK_FLAG_BACKWARD);
++ flags |
++ AVSEEK_FLAG_BACKWARD |
++ (st2->codec->codec_type != AVMEDIA_TYPE_VIDEO ? AVSEEK_FLAG_ANY : 0));
+ if (index < 0)
+ index = 0;
++ ast2->seek_pos = st2->index_entries[index].pos;
++ pos_min = FFMIN(pos_min,ast2->seek_pos);
+ }
- for(i = 0; i < s->nb_streams; i++) {
++ for (i = 0; i < s->nb_streams; i++) {
+ AVStream *st2 = s->streams[i];
+ AVIStream *ast2 = st2->priv_data;
- if (!avi->non_interleaved) {
- while (index > 0 && st2->index_entries[index].pos > pos)
- index--;
- while (index + 1 < st2->nb_index_entries &&
- st2->index_entries[index].pos < pos)
- index++;
- }
+ if (ast2->sub_ctx || st2->nb_index_entries <= 0)
+ continue;
- av_dlog(s, "%"PRId64" %d %"PRId64"\n",
- timestamp, index, st2->index_entries[index].timestamp);
- /* extract the current frame number */
+ index = av_index_search_timestamp(
+ st2,
+ av_rescale_q(timestamp, st->time_base, st2->time_base) * FFMAX(ast2->sample_size, 1),
+ flags | AVSEEK_FLAG_BACKWARD | (st2->codec->codec_type != AVMEDIA_TYPE_VIDEO ? AVSEEK_FLAG_ANY : 0));
- if(index<0)
- index=0;
- while(!avi->non_interleaved && index>0 && st2->index_entries[index-1].pos >= pos_min)
++ if (index < 0)
++ index = 0;
++ while (!avi->non_interleaved && index>0 && st2->index_entries[index-1].pos >= pos_min)
+ index--;
ast2->frame_offset = st2->index_entries[index].timestamp;
}
/* do the seek */
- avio_seek(s->pb, pos, SEEK_SET);
+ if (avio_seek(s->pb, pos_min, SEEK_SET) < 0) {
+ av_log(s, AV_LOG_ERROR, "Seek failed\n");
+ return -1;
+ }
- avi->stream_index= -1;
- avi->dts_max= INT_MIN;
+ avi->stream_index = -1;
++ avi->dts_max = INT_MIN;
return 0;
}