uint64_t pts;
} MlvContext;
-static int probe(AVProbeData *p)
+static int read_close(AVFormatContext *s);
+
+static int probe(const AVProbeData *p)
{
if (AV_RL32(p->buf) == MKTAG('M','L','V','I') &&
AV_RL32(p->buf + 4) >= 52 &&
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");
}
} 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) {
}
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;
}
{
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;
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);
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)
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),