avformat/cdxl: improve frame rate guessing for standard cdxl

Use audio size and sample rate to get real frame rate.
Also make seeking more robust.
This commit is contained in:
Paul B Mahol 2021-02-05 00:35:18 +01:00
parent fb9c56bbd5
commit cba716f55e
7 changed files with 55 additions and 49 deletions

View File

@ -31,12 +31,13 @@
typedef struct CDXLDemuxContext {
AVClass *class;
int read_chunk;
int frate;
AVRational frate;
int srate;
uint8_t header[CDXL_HEADER_SIZE];
int video_stream_index;
int audio_stream_index;
int64_t filesize;
int64_t pos;
} CDXLDemuxContext;
static int cdxl_read_probe(const AVProbeData *p)
@ -117,34 +118,34 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
AVIOContext *pb = s->pb;
uint32_t current_size, video_size, image_size;
uint16_t audio_size, palette_size, width, height;
int64_t pos;
int type, format, frames, ret;
int channels, type, format, ret;
if (avio_feof(pb))
return AVERROR_EOF;
pos = avio_tell(pb);
if (!cdxl->read_chunk &&
avio_read(pb, cdxl->header, CDXL_HEADER_SIZE) != CDXL_HEADER_SIZE)
return AVERROR_EOF;
if (!cdxl->read_chunk) {
cdxl->pos = avio_tell(pb);
if (avio_read(pb, cdxl->header, CDXL_HEADER_SIZE) != CDXL_HEADER_SIZE)
return AVERROR_EOF;
}
if (cdxl->header[0] > 1) {
av_log(s, AV_LOG_ERROR, "unsupported cdxl file\n");
return AVERROR_INVALIDDATA;
}
type = cdxl->header[0];
channels = 1 + !!(cdxl->header[1] & 0x10);
format = cdxl->header[1] & 0xE0;
current_size = AV_RB32(&cdxl->header[2]);
width = AV_RB16(&cdxl->header[14]);
height = AV_RB16(&cdxl->header[16]);
palette_size = AV_RB16(&cdxl->header[20]);
audio_size = AV_RB16(&cdxl->header[22]) * (1 + !!(cdxl->header[1] & 0x10));
audio_size = AV_RB16(&cdxl->header[22]) * channels;
cdxl->srate = AV_RB16(&cdxl->header[24]);
if (!cdxl->srate)
if (!cdxl->srate && audio_size)
cdxl->srate = 11025;
cdxl->frate = cdxl->header[26];
if (!cdxl->frate)
cdxl->frate = 25;
cdxl->frate.num = cdxl->header[26];
cdxl->frate.den = 1;
if (cdxl->header[19] == 0 ||
FFALIGN(width, 16) * (uint64_t)height * cdxl->header[19] > INT_MAX)
return AVERROR_INVALIDDATA;
@ -160,6 +161,12 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
if (current_size < (uint64_t)audio_size + video_size + CDXL_HEADER_SIZE)
return AVERROR_INVALIDDATA;
if (!cdxl->frate.num && audio_size && cdxl->srate > 0) {
cdxl->frate = (AVRational){ cdxl->srate, audio_size };
} else if (!cdxl->frate.num) {
cdxl->frate.num = 15;
}
if (cdxl->read_chunk && audio_size) {
if (cdxl->audio_stream_index == -1) {
AVStream *st = avformat_new_stream(s, NULL);
@ -169,25 +176,22 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_tag = 0;
st->codecpar->codec_id = AV_CODEC_ID_PCM_S8_PLANAR;
if (cdxl->header[1] & 0x10) {
st->codecpar->channels = 2;
st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
} else {
st->codecpar->channels = 1;
st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
}
st->codecpar->channels = channels;
st->codecpar->channel_layout = channels == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
st->codecpar->sample_rate= cdxl->srate;
st->start_time = 0;
cdxl->audio_stream_index = st->index;
avpriv_set_pts_info(st, 64, 1, cdxl->srate);
if (current_size && cdxl->filesize > 0 && audio_size > 0)
st->duration = (cdxl->filesize / current_size) * audio_size / channels;
}
ret = av_get_packet(pb, pkt, audio_size);
if (ret < 0)
return ret;
pkt->stream_index = cdxl->audio_stream_index;
pkt->pos = pos;
pkt->duration = audio_size;
pkt->pos = cdxl->pos;
pkt->duration = audio_size / channels;
cdxl->read_chunk = 0;
} else {
if (cdxl->video_stream_index == -1) {
@ -201,20 +205,11 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
st->codecpar->width = width;
st->codecpar->height = height;
if (audio_size + video_size && cdxl->filesize > 0) {
frames = cdxl->filesize / (audio_size + video_size);
if (cdxl->frate)
st->duration = frames;
else
st->duration = frames * (int64_t)audio_size;
}
if (current_size && cdxl->filesize > 0)
st->nb_frames = cdxl->filesize / current_size;
st->start_time = 0;
cdxl->video_stream_index = st->index;
if (cdxl->frate)
avpriv_set_pts_info(st, 64, 1, cdxl->frate);
else
avpriv_set_pts_info(st, 64, 1, cdxl->srate);
avpriv_set_pts_info(st, 64, cdxl->frate.den, cdxl->frate.num);
}
if ((ret = av_new_packet(pkt, video_size + CDXL_HEADER_SIZE)) < 0)
@ -227,8 +222,8 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
av_shrink_packet(pkt, CDXL_HEADER_SIZE + ret);
pkt->stream_index = cdxl->video_stream_index;
pkt->flags |= AV_PKT_FLAG_KEY;
pkt->pos = pos;
pkt->duration = cdxl->frate ? 1 : audio_size ? audio_size : 220;
pkt->pos = cdxl->pos;
pkt->duration = 1;
cdxl->read_chunk = audio_size;
}
@ -237,6 +232,16 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
return ret;
}
static int read_seek(AVFormatContext *s, int stream_index,
int64_t timestamp, int flags)
{
CDXLDemuxContext *cdxl = s->priv_data;
cdxl->read_chunk = 0;
return -1;
}
AVInputFormat ff_cdxl_demuxer = {
.name = "cdxl",
.long_name = NULL_IF_CONFIG_SMALL("Commodore CDXL video"),
@ -244,6 +249,7 @@ AVInputFormat ff_cdxl_demuxer = {
.read_probe = cdxl_read_probe,
.read_header = cdxl_read_header,
.read_packet = cdxl_read_packet,
.read_seek = read_seek,
.extensions = "cdxl,xl",
.flags = AVFMT_GENERIC_INDEX,
};

View File

@ -1,4 +1,4 @@
#tb 0: 1/25
#tb 0: 1/15
#media_type 0: video
#codec_id 0: rawvideo
#dimensions 0: 162x130

View File

@ -1,4 +1,4 @@
#tb 0: 1/25
#tb 0: 628/3675
#media_type 0: video
#codec_id 0: cdxl
#dimensions 0: 176x128
@ -12,19 +12,19 @@
0, 0, 0, 1, 22688, 0xc954a244
1, 0, 0, 1884, 1884, 0x06925e3e
0, 1, 1, 1, 22688, 0x3ee4a304
0, 2, 2, 1, 22688, 0x9777a305
0, 3, 3, 1, 22688, 0xf00aa306
0, 4, 4, 1, 22688, 0x48aca307
1, 1884, 1884, 1884, 1884, 0x1957ab65
0, 5, 5, 1, 22688, 0xa13fa308
0, 6, 6, 1, 22688, 0xf9d2a309
0, 7, 7, 1, 22688, 0x5274a30a
0, 8, 8, 1, 22688, 0xab07a30b
0, 2, 2, 1, 22688, 0x9777a305
1, 3768, 3768, 1884, 1884, 0x7fcd6e47
0, 9, 9, 1, 17896, 0x1a696b6e
0, 3, 3, 1, 22688, 0xf00aa306
1, 5652, 5652, 1884, 1884, 0xc974878e
0, 4, 4, 1, 22688, 0x48aca307
1, 7536, 7536, 1884, 1884, 0xecb5c4c8
0, 5, 5, 1, 22688, 0xa13fa308
1, 9420, 9420, 1884, 1884, 0x87adce5f
0, 6, 6, 1, 22688, 0xf9d2a309
1, 11304, 11304, 1884, 1884, 0x3cf097e4
0, 7, 7, 1, 22688, 0x5274a30a
1, 13188, 13188, 1884, 1884, 0xcc218105
0, 8, 8, 1, 22688, 0xab07a30b
1, 15072, 15072, 1884, 1884, 0xf685762f
0, 9, 9, 1, 17896, 0x1a696b6e

View File

@ -1,4 +1,4 @@
#tb 0: 1/25
#tb 0: 12/121
#media_type 0: video
#codec_id 0: rawvideo
#dimensions 0: 160x120

View File

@ -1,4 +1,4 @@
#tb 0: 1/25
#tb 0: 628/3675
#media_type 0: video
#codec_id 0: rawvideo
#dimensions 0: 176x128

View File

@ -1,4 +1,4 @@
#tb 0: 1/25
#tb 0: 1/15
#media_type 0: video
#codec_id 0: rawvideo
#dimensions 0: 176x128

View File

@ -1,4 +1,4 @@
#tb 0: 1/25
#tb 0: 1001/30000
#media_type 0: video
#codec_id 0: rawvideo
#dimensions 0: 128x80