AVIContext *avi = s->priv_data;
int n, au_byterate, au_ssize, au_scale, nb_frames = 0;
int64_t file_size;
- AVCodecContext* stream;
+ AVCodecContext *stream;
file_size = avio_tell(pb);
- for(n = 0; n < s->nb_streams; n++) {
- AVIStream *avist= s->streams[n]->priv_data;
+ for (n = 0; n < s->nb_streams; n++) {
+ AVIStream *avist = s->streams[n]->priv_data;
- assert(avist->frames_hdr_strm);
+ av_assert0(avist->frames_hdr_strm);
stream = s->streams[n]->codec;
avio_seek(pb, avist->frames_hdr_strm, SEEK_SET);
ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
- if(au_ssize == 0) {
+ if (au_ssize == 0)
avio_wl32(pb, avist->packet_count);
- } else {
+ else
avio_wl32(pb, avist->audio_strm_length / au_ssize);
- }
- if(stream->codec_type == AVMEDIA_TYPE_VIDEO)
+ if (stream->codec_type == AVMEDIA_TYPE_VIDEO)
nb_frames = FFMAX(nb_frames, avist->packet_count);
}
- if(riff_id == 1) {
+ if (riff_id == 1) {
- assert(avi->frames_hdr_all);
+ av_assert0(avi->frames_hdr_all);
avio_seek(pb, avi->frames_hdr_all, SEEK_SET);
avio_wl32(pb, nb_frames);
}
if (s->nb_streams > AVI_MAX_STREAM_COUNT) {
av_log(s, AV_LOG_ERROR, "AVI does not support >%d streams\n",
AVI_MAX_STREAM_COUNT);
- return -1;
+ return AVERROR(EINVAL);
}
- for(n=0;n<s->nb_streams;n++) {
- s->streams[n]->priv_data= av_mallocz(sizeof(AVIStream));
- if(!s->streams[n]->priv_data)
+ for (n = 0; n < s->nb_streams; n++) {
+ s->streams[n]->priv_data = av_mallocz(sizeof(AVIStream));
+ if (!s->streams[n]->priv_data)
return AVERROR(ENOMEM);
}
ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
- if(stream->codec_id == AV_CODEC_ID_XSUB)
+ if ( stream->codec_type == AVMEDIA_TYPE_VIDEO
+ && stream->codec_id != AV_CODEC_ID_XSUB
+ && au_byterate > 1000LL*au_scale) {
+ au_byterate = 600;
+ au_scale = 1;
+ }
+ avpriv_set_pts_info(s->streams[i], 64, au_scale, au_byterate);
++ if (stream->codec_id == AV_CODEC_ID_XSUB)
+ au_scale = au_byterate = 0;
+
avio_wl32(pb, au_scale); /* scale */
avio_wl32(pb, au_byterate); /* rate */
- avpriv_set_pts_info(s->streams[i], 64, au_scale, au_byterate);
avio_wl32(pb, 0); /* start */
- avist->frames_hdr_strm = avio_tell(pb); /* remember this offset to fill later */
+ /* remember this offset to fill later */
+ avist->frames_hdr_strm = avio_tell(pb);
if (!pb->seekable)
- avio_wl32(pb, AVI_MAX_RIFF_SIZE); /* FIXME: this may be broken, but who cares */
+ /* FIXME: this may be broken, but who cares */
+ avio_wl32(pb, AVI_MAX_RIFF_SIZE);
else
- avio_wl32(pb, 0); /* length, XXX: filled later */
+ avio_wl32(pb, 0); /* length, XXX: filled later */
/* suggested buffer size */ //FIXME set at the end to largest chunk
- if(stream->codec_type == AVMEDIA_TYPE_VIDEO)
+ if (stream->codec_type == AVMEDIA_TYPE_VIDEO)
avio_wl32(pb, 1024 * 1024);
- else if(stream->codec_type == AVMEDIA_TYPE_AUDIO)
+ else if (stream->codec_type == AVMEDIA_TYPE_AUDIO)
avio_wl32(pb, 12 * 1024);
else
avio_wl32(pb, 0);
avio_wl16(pb, stream->height);
ff_end_tag(pb, strh);
- if(stream->codec_type != AVMEDIA_TYPE_DATA){
- int ret;
-
- strf = ff_start_tag(pb, "strf");
- switch(stream->codec_type) {
- case AVMEDIA_TYPE_SUBTITLE:
- // XSUB subtitles behave like video tracks, other subtitles
- // are not (yet) supported.
- if (stream->codec_id != AV_CODEC_ID_XSUB) break;
- case AVMEDIA_TYPE_VIDEO:
- ff_put_bmp_header(pb, stream, ff_codec_bmp_tags, 0, 0);
- break;
- case AVMEDIA_TYPE_AUDIO:
- if ((ret = ff_put_wav_header(pb, stream)) < 0) {
- return ret;
+ if (stream->codec_type != AVMEDIA_TYPE_DATA) {
++ int ret;
++
+ strf = ff_start_tag(pb, "strf");
+ switch (stream->codec_type) {
+ case AVMEDIA_TYPE_SUBTITLE:
+ /* XSUB subtitles behave like video tracks, other subtitles
+ * are not (yet) supported. */
+ if (stream->codec_id != AV_CODEC_ID_XSUB)
+ break;
+ case AVMEDIA_TYPE_VIDEO:
- ff_put_bmp_header(pb, stream, ff_codec_bmp_tags, 0);
++ ff_put_bmp_header(pb, stream, ff_codec_bmp_tags, 0, 0);
+ break;
+ case AVMEDIA_TYPE_AUDIO:
- if (ff_put_wav_header(pb, stream) < 0)
- return -1;
++ if ((ret = ff_put_wav_header(pb, stream)) < 0)
++ return ret;
+ break;
+ default:
- return -1;
++ av_log(s, AV_LOG_ERROR,
++ "Invalid or not supported codec type '%s' found in the input\n",
++ (char *)av_x_if_null(av_get_media_type_string(stream->codec_type), "?"));
++ return AVERROR(EINVAL);
}
- break;
- default:
- av_log(s, AV_LOG_ERROR,
- "Invalid or not supported codec type '%s' found in the input\n",
- (char *)av_x_if_null(av_get_media_type_string(stream->codec_type), "?"));
- return AVERROR(EINVAL);
- }
- ff_end_tag(pb, strf);
- if ((t = av_dict_get(s->streams[i]->metadata, "title", NULL, 0))) {
- ff_riff_write_info_tag(s->pb, "strn", t->value);
- t = NULL;
- }
- if(stream->codec_id == AV_CODEC_ID_XSUB
- && (t = av_dict_get(s->streams[i]->metadata, "language", NULL, 0))) {
- const char* langstr = av_convert_lang_to(t->value, AV_LANG_ISO639_1);
- t = NULL;
- if (langstr) {
- char* str = av_asprintf("Subtitle - %s-xx;02", langstr);
- ff_riff_write_info_tag(s->pb, "strn", str);
- av_free(str);
+ ff_end_tag(pb, strf);
+ if ((t = av_dict_get(s->streams[i]->metadata, "title", NULL, 0))) {
+ ff_riff_write_info_tag(s->pb, "strn", t->value);
+ t = NULL;
+ }
++ if (stream->codec_id == AV_CODEC_ID_XSUB
++ && (t = av_dict_get(s->streams[i]->metadata, "language", NULL, 0))) {
++ const char* langstr = av_convert_lang_to(t->value, AV_LANG_ISO639_1);
++ t = NULL;
++ if (langstr) {
++ char* str = av_asprintf("Subtitle - %s-xx;02", langstr);
++ ff_riff_write_info_tag(s->pb, "strn", str);
++ av_free(str);
++ }
+ }
}
- }
if (pb->seekable) {
unsigned char tag[5];
char ix_tag[] = "ix00";
int i, j;
- assert(pb->seekable);
+ av_assert0(pb->seekable);
- if (avi->riff_id > AVI_MASTER_INDEX_SIZE)
- return -1;
+ if (avi->riff_id > AVI_MASTER_INDEX_SIZE) {
+ av_log(s, AV_LOG_ERROR, "Invalid riff index %d > %d\n",
+ avi->riff_id, AVI_MASTER_INDEX_SIZE);
+ return AVERROR(EINVAL);
+ }
- for (i=0;i<s->nb_streams;i++) {
- AVIStream *avist= s->streams[i]->priv_data;
- int64_t ix, pos;
-
- avi_stream2fourcc(tag, i, s->streams[i]->codec->codec_type);
- ix_tag[3] = '0' + i;
-
- /* Writing AVI OpenDML leaf index chunk */
- ix = avio_tell(pb);
- ffio_wfourcc(pb, ix_tag); /* ix?? */
- avio_wl32(pb, avist->indexes.entry * 8 + 24);
- /* chunk size */
- avio_wl16(pb, 2); /* wLongsPerEntry */
- avio_w8(pb, 0); /* bIndexSubType (0 == frame index) */
- avio_w8(pb, 1); /* bIndexType (1 == AVI_INDEX_OF_CHUNKS) */
- avio_wl32(pb, avist->indexes.entry);
- /* nEntriesInUse */
- ffio_wfourcc(pb, tag); /* dwChunkId */
- avio_wl64(pb, avi->movi_list);/* qwBaseOffset */
- avio_wl32(pb, 0); /* dwReserved_3 (must be 0) */
-
- for (j=0; j<avist->indexes.entry; j++) {
- AVIIentry* ie = avi_get_ientry(&avist->indexes, j);
- avio_wl32(pb, ie->pos + 8);
- avio_wl32(pb, ((uint32_t)ie->len & ~0x80000000) |
+ for (i = 0; i < s->nb_streams; i++) {
+ AVIStream *avist = s->streams[i]->priv_data;
+ int64_t ix, pos;
+
+ avi_stream2fourcc(tag, i, s->streams[i]->codec->codec_type);
+ ix_tag[3] = '0' + i;
+
+ /* Writing AVI OpenDML leaf index chunk */
+ ix = avio_tell(pb);
+ ffio_wfourcc(pb, ix_tag); /* ix?? */
+ avio_wl32(pb, avist->indexes.entry * 8 + 24);
+ /* chunk size */
+ avio_wl16(pb, 2); /* wLongsPerEntry */
+ avio_w8(pb, 0); /* bIndexSubType (0 == frame index) */
+ avio_w8(pb, 1); /* bIndexType (1 == AVI_INDEX_OF_CHUNKS) */
+ avio_wl32(pb, avist->indexes.entry);
+ /* nEntriesInUse */
+ ffio_wfourcc(pb, tag); /* dwChunkId */
+ avio_wl64(pb, avi->movi_list); /* qwBaseOffset */
+ avio_wl32(pb, 0); /* dwReserved_3 (must be 0) */
+
+ for (j = 0; j < avist->indexes.entry; j++) {
+ AVIIentry *ie = avi_get_ientry(&avist->indexes, j);
+ avio_wl32(pb, ie->pos + 8);
+ avio_wl32(pb, ((uint32_t) ie->len & ~0x80000000) |
(ie->flags & 0x10 ? 0 : 0x80000000));
- }
- avio_flush(pb);
- pos = avio_tell(pb);
-
- /* Updating one entry in the AVI OpenDML master index */
- avio_seek(pb, avist->indexes.indx_start - 8, SEEK_SET);
- ffio_wfourcc(pb, "indx"); /* enabling this entry */
- avio_skip(pb, 8);
- avio_wl32(pb, avi->riff_id); /* nEntriesInUse */
- avio_skip(pb, 16*avi->riff_id);
- avio_wl64(pb, ix); /* qwOffset */
- avio_wl32(pb, pos - ix); /* dwSize */
- avio_wl32(pb, avist->indexes.entry); /* dwDuration */
-
- avio_seek(pb, pos, SEEK_SET);
+ }
+ avio_flush(pb);
+ pos = avio_tell(pb);
+
+ /* Updating one entry in the AVI OpenDML master index */
+ avio_seek(pb, avist->indexes.indx_start - 8, SEEK_SET);
+ ffio_wfourcc(pb, "indx"); /* enabling this entry */
+ avio_skip(pb, 8);
+ avio_wl32(pb, avi->riff_id); /* nEntriesInUse */
+ avio_skip(pb, 16 * avi->riff_id);
+ avio_wl64(pb, ix); /* qwOffset */
+ avio_wl32(pb, pos - ix); /* dwSize */
+ avio_wl32(pb, avist->indexes.entry); /* dwDuration */
+
+ avio_seek(pb, pos, SEEK_SET);
}
return 0;
}
static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
{
- AVIContext *avi = s->priv_data;
- AVIOContext *pb = s->pb;
unsigned char tag[5];
- unsigned int flags=0;
- const int stream_index= pkt->stream_index;
- AVIStream *avist= s->streams[stream_index]->priv_data;
- AVCodecContext *enc= s->streams[stream_index]->codec;
- int size= pkt->size;
+ unsigned int flags = 0;
+ const int stream_index = pkt->stream_index;
+ int size = pkt->size;
+ AVIContext *avi = s->priv_data;
+ AVIOContext *pb = s->pb;
+ AVIStream *avist = s->streams[stream_index]->priv_data;
+ AVCodecContext *enc = s->streams[stream_index]->codec;
- while(enc->block_align==0 && pkt->dts != AV_NOPTS_VALUE && pkt->dts > avist->packet_count && enc->codec_id != AV_CODEC_ID_XSUB && avist->packet_count){
+ av_dlog(s, "dts:%s packet_count:%d stream_index:%d\n", av_ts2str(pkt->dts), avist->packet_count, stream_index);
- pkt->dts > avist->packet_count) {
+ while (enc->block_align == 0 && pkt->dts != AV_NOPTS_VALUE &&
++ pkt->dts > avist->packet_count && enc->codec_id != AV_CODEC_ID_XSUB && avist->packet_count) {
AVPacket empty_packet;
- if(pkt->dts - avist->packet_count > 60000){
++ if (pkt->dts - avist->packet_count > 60000) {
+ av_log(s, AV_LOG_ERROR, "Too large number of skipped frames %"PRId64" > 60000\n", pkt->dts - avist->packet_count);
+ return AVERROR(EINVAL);
+ }
+
av_init_packet(&empty_packet);
- empty_packet.size= 0;
- empty_packet.data= NULL;
- empty_packet.stream_index= stream_index;
+ empty_packet.size = 0;
+ empty_packet.data = NULL;
+ empty_packet.stream_index = stream_index;
avi_write_packet(s, &empty_packet);
+ av_dlog(s, "dup dts:%s packet_count:%d\n", av_ts2str(pkt->dts), avist->packet_count);
}
avist->packet_count++;
}
avi_stream2fourcc(tag, stream_index, enc->codec_type);
- if(pkt->flags&AV_PKT_FLAG_KEY)
+ if (pkt->flags & AV_PKT_FLAG_KEY)
flags = 0x10;
- if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
- avist->audio_strm_length += size;
- }
+ if (enc->codec_type == AVMEDIA_TYPE_AUDIO)
+ avist->audio_strm_length += size;
if (s->pb->seekable) {
- AVIIndex* idx = &avist->indexes;
- int err;
+ AVIIndex *idx = &avist->indexes;
int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE;
int id = idx->entry % AVI_INDEX_CLUSTER_SIZE;
if (idx->ents_allocated <= idx->entry) {
- if ((err = av_reallocp(&idx->cluster,
- (cl + 1) * sizeof(*idx->cluster))) < 0) {
+ idx->cluster = av_realloc_f(idx->cluster, sizeof(void*), cl+1);
+ if (!idx->cluster) {
idx->ents_allocated = 0;
- idx->entry = 0;
+ idx->entry = 0;
- return err;
+ return AVERROR(ENOMEM);
}
- idx->cluster[cl] = av_malloc(AVI_INDEX_CLUSTER_SIZE*sizeof(AVIIentry));
+ idx->cluster[cl] =
+ av_malloc(AVI_INDEX_CLUSTER_SIZE * sizeof(AVIIentry));
if (!idx->cluster[cl])
- return -1;
+ return AVERROR(ENOMEM);
idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE;
}
}
}
- for (i=0; i<s->nb_streams; i++) {
- AVIStream *avist= s->streams[i]->priv_data;
- for (j=0; j<avist->indexes.ents_allocated/AVI_INDEX_CLUSTER_SIZE; j++)
- av_freep(&avist->indexes.cluster[j]);
- av_freep(&avist->indexes.cluster);
- avist->indexes.ents_allocated = avist->indexes.entry = 0;
+ for (i = 0; i < s->nb_streams; i++) {
+ AVIStream *avist = s->streams[i]->priv_data;
+ for (j = 0; j < avist->indexes.ents_allocated / AVI_INDEX_CLUSTER_SIZE; j++)
- av_free(avist->indexes.cluster[j]);
++ av_freep(&avist->indexes.cluster[j]);
+ av_freep(&avist->indexes.cluster);
+ avist->indexes.ents_allocated = avist->indexes.entry = 0;
}
return res;