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:
		
							parent
							
								
									fb9c56bbd5
								
							
						
					
					
						commit
						cba716f55e
					
				@ -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,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
#tb 0: 1/25
 | 
			
		||||
#tb 0: 1/15
 | 
			
		||||
#media_type 0: video
 | 
			
		||||
#codec_id 0: rawvideo
 | 
			
		||||
#dimensions 0: 162x130
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
#tb 0: 1/25
 | 
			
		||||
#tb 0: 12/121
 | 
			
		||||
#media_type 0: video
 | 
			
		||||
#codec_id 0: rawvideo
 | 
			
		||||
#dimensions 0: 160x120
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
#tb 0: 1/25
 | 
			
		||||
#tb 0: 628/3675
 | 
			
		||||
#media_type 0: video
 | 
			
		||||
#codec_id 0: rawvideo
 | 
			
		||||
#dimensions 0: 176x128
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
#tb 0: 1/25
 | 
			
		||||
#tb 0: 1/15
 | 
			
		||||
#media_type 0: video
 | 
			
		||||
#codec_id 0: rawvideo
 | 
			
		||||
#dimensions 0: 176x128
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
#tb 0: 1/25
 | 
			
		||||
#tb 0: 1001/30000
 | 
			
		||||
#media_type 0: video
 | 
			
		||||
#codec_id 0: rawvideo
 | 
			
		||||
#dimensions 0: 128x80
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user