[FFmpeg-cvslog] avformat/cdxl: add support for custom 24bit pal8 formats

Paul B Mahol git at videolan.org
Wed Feb 3 20:12:06 EET 2021


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Wed Feb  3 18:35:59 2021 +0100| [e8189515050ae2e4e204f1f0aa9d0cdca3169903] | committer: Paul B Mahol

avformat/cdxl: add support for custom 24bit pal8 formats

Also stop discarding half of audio samples and use planar pcm s8.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=e8189515050ae2e4e204f1f0aa9d0cdca3169903
---

 libavcodec/cdxl.c         | 29 ++++++++++++++++++++---------
 libavformat/cdxl.c        | 28 ++++++++++++++++------------
 tests/ref/fate/cdxl-demux |  2 +-
 3 files changed, 37 insertions(+), 22 deletions(-)

diff --git a/libavcodec/cdxl.c b/libavcodec/cdxl.c
index 96ae14c418..056c3577ab 100644
--- a/libavcodec/cdxl.c
+++ b/libavcodec/cdxl.c
@@ -43,6 +43,7 @@
 typedef struct CDXLVideoContext {
     AVCodecContext *avctx;
     int            bpp;
+    int            type;
     int            format;
     int            padded_bits;
     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)
 {
-    int i;
-
-    for (i = 0; i < c->palette_size / 2; i++) {
-        unsigned rgb = AV_RB16(&c->palette[i * 2]);
-        unsigned r   = ((rgb >> 8) & 0xF) * 0x11;
-        unsigned g   = ((rgb >> 4) & 0xF) * 0x11;
-        unsigned b   =  (rgb       & 0xF) * 0x11;
-        AV_WN32(&new_palette[i], (0xFFU << 24) | (r << 16) | (g << 8) | b);
+    if (c->type == 1) {
+        for (int i = 0; i < c->palette_size / 2; i++) {
+            unsigned rgb = AV_RB16(&c->palette[i * 2]);
+            unsigned r   = ((rgb >> 8) & 0xF) * 0x11;
+            unsigned g   = ((rgb >> 4) & 0xF) * 0x11;
+            unsigned b   =  (rgb       & 0xF) * 0x11;
+            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)
         return AVERROR_INVALIDDATA;
+    c->type         = buf[0];
     encoding        = buf[1] & 7;
     c->format       = buf[1] & 0xE0;
     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_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;
     if (buf_size < c->palette_size + 32)
         return AVERROR_INVALIDDATA;
diff --git a/libavformat/cdxl.c b/libavformat/cdxl.c
index 5718fc3e21..0c7d021b8f 100644
--- a/libavformat/cdxl.c
+++ b/libavformat/cdxl.c
@@ -47,16 +47,18 @@ static int cdxl_read_probe(const AVProbeData *p)
     if (p->buf_size < CDXL_HEADER_SIZE)
         return 0;
 
-    /* reserved bytes should always be set to 0 */
-    if (AV_RN64(&p->buf[24]) || AV_RN16(&p->buf[10]))
+    /* check type */
+    if (p->buf[0] > 1)
         return 0;
 
-    /* check type */
-    if (p->buf[0] != 1)
+    /* reserved bytes should always be set to 0 */
+    if (p->buf[0] == 1 && (AV_RN64(&p->buf[24]) || AV_RN16(&p->buf[10])))
         return 0;
 
     /* 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;
 
     /* 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;
     uint16_t audio_size, palette_size, width, height;
     int64_t  pos;
-    int      format, frames, ret;
+    int      type, format, frames, ret;
 
     if (avio_feof(pb))
         return AVERROR_EOF;
@@ -120,17 +122,18 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
     if (!cdxl->read_chunk &&
         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, "non-standard cdxl file\n");
+    if (cdxl->header[0] > 1) {
+        av_log(s, AV_LOG_ERROR, "unsupported cdxl file\n");
         return AVERROR_INVALIDDATA;
     }
 
+    type         = cdxl->header[0];
     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]);
+    audio_size   = AV_RB16(&cdxl->header[22]) * (1 + !!(cdxl->header[1] & 0x10));
     if (cdxl->header[19] == 0 ||
         FFALIGN(width, 16) * (uint64_t)height * cdxl->header[19] > INT_MAX)
         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;
     video_size   = palette_size + image_size;
 
-    if (palette_size > 512)
+    if ((type == 1 && palette_size > 512) ||
+        (type == 0 && palette_size > 768))
         return AVERROR_INVALIDDATA;
     if (current_size < (uint64_t)audio_size + video_size + CDXL_HEADER_SIZE)
         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_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) {
                 st->codecpar->channels       = 2;
                 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) {
                 frames = cdxl->filesize / (audio_size + video_size);
 
-                if(cdxl->framerate)
+                if (cdxl->framerate)
                     st->duration = frames;
                 else
                     st->duration = frames * (int64_t)audio_size;
diff --git a/tests/ref/fate/cdxl-demux b/tests/ref/fate/cdxl-demux
index f1334755aa..f919b67881 100644
--- a/tests/ref/fate/cdxl-demux
+++ b/tests/ref/fate/cdxl-demux
@@ -5,7 +5,7 @@
 #sar 0: 0/1
 #tb 1: 1/11025
 #media_type 1: audio
-#codec_id 1: pcm_s8
+#codec_id 1: pcm_s8_planar
 #sample_rate 1: 11025
 #channel_layout 1: 4
 #channel_layout_name 1: mono



More information about the ffmpeg-cvslog mailing list