mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-08 13:22:53 +02:00
avformat/cdxl: add support for custom 24bit pal8 formats
Also stop discarding half of audio samples and use planar pcm s8.
This commit is contained in:
parent
e6254d5ab9
commit
e818951505
@ -43,6 +43,7 @@
|
|||||||
typedef struct CDXLVideoContext {
|
typedef struct CDXLVideoContext {
|
||||||
AVCodecContext *avctx;
|
AVCodecContext *avctx;
|
||||||
int bpp;
|
int bpp;
|
||||||
|
int type;
|
||||||
int format;
|
int format;
|
||||||
int padded_bits;
|
int padded_bits;
|
||||||
const uint8_t *palette;
|
const uint8_t *palette;
|
||||||
@ -65,14 +66,19 @@ static av_cold int cdxl_decode_init(AVCodecContext *avctx)
|
|||||||
|
|
||||||
static void import_palette(CDXLVideoContext *c, uint32_t *new_palette)
|
static void import_palette(CDXLVideoContext *c, uint32_t *new_palette)
|
||||||
{
|
{
|
||||||
int i;
|
if (c->type == 1) {
|
||||||
|
for (int i = 0; i < c->palette_size / 2; i++) {
|
||||||
for (i = 0; i < c->palette_size / 2; i++) {
|
unsigned rgb = AV_RB16(&c->palette[i * 2]);
|
||||||
unsigned rgb = AV_RB16(&c->palette[i * 2]);
|
unsigned r = ((rgb >> 8) & 0xF) * 0x11;
|
||||||
unsigned r = ((rgb >> 8) & 0xF) * 0x11;
|
unsigned g = ((rgb >> 4) & 0xF) * 0x11;
|
||||||
unsigned g = ((rgb >> 4) & 0xF) * 0x11;
|
unsigned b = (rgb & 0xF) * 0x11;
|
||||||
unsigned b = (rgb & 0xF) * 0x11;
|
AV_WN32(&new_palette[i], (0xFFU << 24) | (r << 16) | (g << 8) | b);
|
||||||
AV_WN32(&new_palette[i], (0xFFU << 24) | (r << 16) | (g << 8) | b);
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < c->palette_size / 3; i++) {
|
||||||
|
unsigned rgb = AV_RB24(&c->palette[i * 3]);
|
||||||
|
AV_WN32(&new_palette[i], (0xFFU << 24) | rgb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,6 +252,7 @@ static int cdxl_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
|
|
||||||
if (buf_size < 32)
|
if (buf_size < 32)
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
|
c->type = buf[0];
|
||||||
encoding = buf[1] & 7;
|
encoding = buf[1] & 7;
|
||||||
c->format = buf[1] & 0xE0;
|
c->format = buf[1] & 0xE0;
|
||||||
w = AV_RB16(&buf[14]);
|
w = AV_RB16(&buf[14]);
|
||||||
@ -256,7 +263,11 @@ static int cdxl_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
c->video = c->palette + c->palette_size;
|
c->video = c->palette + c->palette_size;
|
||||||
c->video_size = buf_size - c->palette_size - 32;
|
c->video_size = buf_size - c->palette_size - 32;
|
||||||
|
|
||||||
if (c->palette_size > 512)
|
if (c->type > 1)
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
if (c->type == 1 && c->palette_size > 512)
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
if (c->type == 0 && c->palette_size > 768)
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
if (buf_size < c->palette_size + 32)
|
if (buf_size < c->palette_size + 32)
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
|
@ -47,16 +47,18 @@ static int cdxl_read_probe(const AVProbeData *p)
|
|||||||
if (p->buf_size < CDXL_HEADER_SIZE)
|
if (p->buf_size < CDXL_HEADER_SIZE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* reserved bytes should always be set to 0 */
|
/* check type */
|
||||||
if (AV_RN64(&p->buf[24]) || AV_RN16(&p->buf[10]))
|
if (p->buf[0] > 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* check type */
|
/* reserved bytes should always be set to 0 */
|
||||||
if (p->buf[0] != 1)
|
if (p->buf[0] == 1 && (AV_RN64(&p->buf[24]) || AV_RN16(&p->buf[10])))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* check palette size */
|
/* check palette size */
|
||||||
if (AV_RB16(&p->buf[20]) > 512)
|
if (p->buf[0] == 1 && AV_RB16(&p->buf[20]) > 512)
|
||||||
|
return 0;
|
||||||
|
if (p->buf[0] == 0 && AV_RB16(&p->buf[20]) > 768)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* check number of planes */
|
/* check number of planes */
|
||||||
@ -111,7 +113,7 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
uint32_t current_size, video_size, image_size;
|
uint32_t current_size, video_size, image_size;
|
||||||
uint16_t audio_size, palette_size, width, height;
|
uint16_t audio_size, palette_size, width, height;
|
||||||
int64_t pos;
|
int64_t pos;
|
||||||
int format, frames, ret;
|
int type, format, frames, ret;
|
||||||
|
|
||||||
if (avio_feof(pb))
|
if (avio_feof(pb))
|
||||||
return AVERROR_EOF;
|
return AVERROR_EOF;
|
||||||
@ -120,17 +122,18 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
if (!cdxl->read_chunk &&
|
if (!cdxl->read_chunk &&
|
||||||
avio_read(pb, cdxl->header, CDXL_HEADER_SIZE) != CDXL_HEADER_SIZE)
|
avio_read(pb, cdxl->header, CDXL_HEADER_SIZE) != CDXL_HEADER_SIZE)
|
||||||
return AVERROR_EOF;
|
return AVERROR_EOF;
|
||||||
if (cdxl->header[0] != 1) {
|
if (cdxl->header[0] > 1) {
|
||||||
av_log(s, AV_LOG_ERROR, "non-standard cdxl file\n");
|
av_log(s, AV_LOG_ERROR, "unsupported cdxl file\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type = cdxl->header[0];
|
||||||
format = cdxl->header[1] & 0xE0;
|
format = cdxl->header[1] & 0xE0;
|
||||||
current_size = AV_RB32(&cdxl->header[2]);
|
current_size = AV_RB32(&cdxl->header[2]);
|
||||||
width = AV_RB16(&cdxl->header[14]);
|
width = AV_RB16(&cdxl->header[14]);
|
||||||
height = AV_RB16(&cdxl->header[16]);
|
height = AV_RB16(&cdxl->header[16]);
|
||||||
palette_size = AV_RB16(&cdxl->header[20]);
|
palette_size = AV_RB16(&cdxl->header[20]);
|
||||||
audio_size = AV_RB16(&cdxl->header[22]);
|
audio_size = AV_RB16(&cdxl->header[22]) * (1 + !!(cdxl->header[1] & 0x10));
|
||||||
if (cdxl->header[19] == 0 ||
|
if (cdxl->header[19] == 0 ||
|
||||||
FFALIGN(width, 16) * (uint64_t)height * cdxl->header[19] > INT_MAX)
|
FFALIGN(width, 16) * (uint64_t)height * cdxl->header[19] > INT_MAX)
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
@ -140,7 +143,8 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
image_size = FFALIGN(width, 16) * height * cdxl->header[19] / 8;
|
image_size = FFALIGN(width, 16) * height * cdxl->header[19] / 8;
|
||||||
video_size = palette_size + image_size;
|
video_size = palette_size + image_size;
|
||||||
|
|
||||||
if (palette_size > 512)
|
if ((type == 1 && palette_size > 512) ||
|
||||||
|
(type == 0 && palette_size > 768))
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
if (current_size < (uint64_t)audio_size + video_size + CDXL_HEADER_SIZE)
|
if (current_size < (uint64_t)audio_size + video_size + CDXL_HEADER_SIZE)
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
@ -153,7 +157,7 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
|
|
||||||
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
|
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||||
st->codecpar->codec_tag = 0;
|
st->codecpar->codec_tag = 0;
|
||||||
st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
|
st->codecpar->codec_id = AV_CODEC_ID_PCM_S8_PLANAR;
|
||||||
if (cdxl->header[1] & 0x10) {
|
if (cdxl->header[1] & 0x10) {
|
||||||
st->codecpar->channels = 2;
|
st->codecpar->channels = 2;
|
||||||
st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
|
st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||||
@ -189,7 +193,7 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
if (audio_size + video_size && cdxl->filesize > 0) {
|
if (audio_size + video_size && cdxl->filesize > 0) {
|
||||||
frames = cdxl->filesize / (audio_size + video_size);
|
frames = cdxl->filesize / (audio_size + video_size);
|
||||||
|
|
||||||
if(cdxl->framerate)
|
if (cdxl->framerate)
|
||||||
st->duration = frames;
|
st->duration = frames;
|
||||||
else
|
else
|
||||||
st->duration = frames * (int64_t)audio_size;
|
st->duration = frames * (int64_t)audio_size;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#sar 0: 0/1
|
#sar 0: 0/1
|
||||||
#tb 1: 1/11025
|
#tb 1: 1/11025
|
||||||
#media_type 1: audio
|
#media_type 1: audio
|
||||||
#codec_id 1: pcm_s8
|
#codec_id 1: pcm_s8_planar
|
||||||
#sample_rate 1: 11025
|
#sample_rate 1: 11025
|
||||||
#channel_layout 1: 4
|
#channel_layout 1: 4
|
||||||
#channel_layout_name 1: mono
|
#channel_layout_name 1: mono
|
||||||
|
Loading…
Reference in New Issue
Block a user