X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmlvdec.c;h=998bf42dd678fdf6dda017e72df0aa01f1ebab26;hb=bc70684e74a185d7b80c8b80bdedda659cb581b8;hp=68ca2c5e1c257081702cb00a75863b9eab749f31;hpb=3e076faf3b86bb16f746e7c9b0cf3dac5f9a851a;p=ffmpeg diff --git a/libavformat/mlvdec.c b/libavformat/mlvdec.c index 68ca2c5e1c2..998bf42dd67 100644 --- a/libavformat/mlvdec.c +++ b/libavformat/mlvdec.c @@ -52,6 +52,8 @@ typedef struct { uint64_t pts; } MlvContext; +static int read_close(AVFormatContext *s); + static int probe(const AVProbeData *p) { if (AV_RL32(p->buf) == MKTAG('M','L','V','I') && @@ -130,23 +132,25 @@ static int scan_file(AVFormatContext *avctx, AVStream *vst, AVStream *ast, int f break; size -= 16; if (vst && type == MKTAG('R','A','W','I') && size >= 164) { - vst->codecpar->width = avio_rl16(pb); - vst->codecpar->height = avio_rl16(pb); - ret = av_image_check_size(vst->codecpar->width, vst->codecpar->height, 0, avctx); + unsigned width = avio_rl16(pb); + unsigned height = avio_rl16(pb); + unsigned bits_per_coded_sample; + ret = av_image_check_size(width, height, 0, avctx); if (ret < 0) return ret; if (avio_rl32(pb) != 1) avpriv_request_sample(avctx, "raw api version"); avio_skip(pb, 20); // pointer, width, height, pitch, frame_size - vst->codecpar->bits_per_coded_sample = avio_rl32(pb); - if (vst->codecpar->bits_per_coded_sample < 0 || - vst->codecpar->bits_per_coded_sample > (INT_MAX - 7) / (vst->codecpar->width * vst->codecpar->height)) { + bits_per_coded_sample = avio_rl32(pb); + if (bits_per_coded_sample > (INT_MAX - 7) / (width * height)) { av_log(avctx, AV_LOG_ERROR, - "invalid bits_per_coded_sample %d (size: %dx%d)\n", - vst->codecpar->bits_per_coded_sample, - vst->codecpar->width, vst->codecpar->height); + "invalid bits_per_coded_sample %u (size: %ux%u)\n", + bits_per_coded_sample, width, height); return AVERROR_INVALIDDATA; } + vst->codecpar->width = width; + vst->codecpar->height = height; + vst->codecpar->bits_per_coded_sample = bits_per_coded_sample; avio_skip(pb, 8 + 16 + 24); // black_level, white_level, xywh, active_area, exposure_bias if (avio_rl32(pb) != 0x2010100) /* RGGB */ avpriv_request_sample(avctx, "cfa_pattern"); @@ -187,12 +191,12 @@ static int scan_file(AVFormatContext *avctx, AVStream *vst, AVStream *ast, int f } } else if (vst && type == MKTAG('V', 'I', 'D', 'F') && size >= 4) { uint64_t pts = avio_rl32(pb); - ff_add_index_entry(&vst->index_entries, &vst->nb_index_entries, &vst->index_entries_allocated_size, + ff_add_index_entry(&vst->internal->index_entries, &vst->internal->nb_index_entries, &vst->internal->index_entries_allocated_size, avio_tell(pb) - 20, pts, file, 0, AVINDEX_KEYFRAME); size -= 4; } else if (ast && type == MKTAG('A', 'U', 'D', 'F') && size >= 4) { uint64_t pts = avio_rl32(pb); - ff_add_index_entry(&ast->index_entries, &ast->nb_index_entries, &ast->index_entries_allocated_size, + ff_add_index_entry(&ast->internal->index_entries, &ast->internal->nb_index_entries, &ast->internal->index_entries_allocated_size, avio_tell(pb) - 20, pts, file, 0, AVINDEX_KEYFRAME); size -= 4; } else if (vst && type == MKTAG('W','B','A','L') && size >= 28) { @@ -370,21 +374,22 @@ static int read_header(AVFormatContext *avctx) } if (vst) - vst->duration = vst->nb_index_entries; + vst->duration = vst->internal->nb_index_entries; if (ast) - ast->duration = ast->nb_index_entries; + ast->duration = ast->internal->nb_index_entries; - if ((vst && !vst->nb_index_entries) || (ast && !ast->nb_index_entries)) { + if ((vst && !vst->internal->nb_index_entries) || (ast && !ast->internal->nb_index_entries)) { av_log(avctx, AV_LOG_ERROR, "no index entries found\n"); + read_close(avctx); return AVERROR_INVALIDDATA; } if (vst && ast) - avio_seek(pb, FFMIN(vst->index_entries[0].pos, ast->index_entries[0].pos), SEEK_SET); + avio_seek(pb, FFMIN(vst->internal->index_entries[0].pos, ast->internal->index_entries[0].pos), SEEK_SET); else if (vst) - avio_seek(pb, vst->index_entries[0].pos, SEEK_SET); + avio_seek(pb, vst->internal->index_entries[0].pos, SEEK_SET); else if (ast) - avio_seek(pb, ast->index_entries[0].pos, SEEK_SET); + avio_seek(pb, ast->internal->index_entries[0].pos, SEEK_SET); return 0; } @@ -393,10 +398,14 @@ static int read_packet(AVFormatContext *avctx, AVPacket *pkt) { MlvContext *mlv = avctx->priv_data; AVIOContext *pb; - AVStream *st = avctx->streams[mlv->stream_index]; + AVStream *st; int index, ret; unsigned int size, space; + if (!avctx->nb_streams) + return AVERROR_EOF; + + st = avctx->streams[mlv->stream_index]; if (mlv->pts >= st->duration) return AVERROR_EOF; @@ -406,8 +415,12 @@ static int read_packet(AVFormatContext *avctx, AVPacket *pkt) return AVERROR(EIO); } - pb = mlv->pb[st->index_entries[index].size]; - avio_seek(pb, st->index_entries[index].pos, SEEK_SET); + pb = mlv->pb[st->internal->index_entries[index].size]; + if (!pb) { + ret = FFERROR_REDO; + goto next_packet; + } + avio_seek(pb, st->internal->index_entries[index].pos, SEEK_SET); avio_skip(pb, 4); // blockType size = avio_rl32(pb); @@ -435,12 +448,14 @@ static int read_packet(AVFormatContext *avctx, AVPacket *pkt) pkt->stream_index = mlv->stream_index; pkt->pts = mlv->pts; + ret = 0; +next_packet: mlv->stream_index++; if (mlv->stream_index == avctx->nb_streams) { mlv->stream_index = 0; mlv->pts++; } - return 0; + return ret; } static int read_seek(AVFormatContext *avctx, int stream_index, int64_t timestamp, int flags) @@ -462,12 +477,11 @@ static int read_close(AVFormatContext *s) MlvContext *mlv = s->priv_data; int i; for (i = 0; i < 100; i++) - if (mlv->pb[i]) - ff_format_io_close(s, &mlv->pb[i]); + ff_format_io_close(s, &mlv->pb[i]); return 0; } -AVInputFormat ff_mlv_demuxer = { +const AVInputFormat ff_mlv_demuxer = { .name = "mlv", .long_name = NULL_IF_CONFIG_SMALL("Magic Lantern Video (MLV)"), .priv_data_size = sizeof(MlvContext),