Unified · Split
| @@ -6,6 +6,7 @@ version <next>: · 5 unmodified lines | ||
| 6 | 6 | - XWD encoder and decoder |
| 7 | 7 | - Support for fragmentation in the mov/mp4 muxer |
| 8 | 8 | - ISMV (Smooth Streaming) muxer |
| 9 | +- CDXL demuxer and decoder | |
| 9 | 10 | |
| 10 | 11 | |
| 11 | 12 | version 0.8: |
| @@ -131,6 +131,8 @@ library: · 130 unmodified lines | ||
| 131 | 131 | @tab Multimedia format used by Delphine Software games. |
| 132 | 132 | @item CD+G @tab @tab X |
| 133 | 133 | @tab Video format used by CD+G karaoke disks |
| 134 | +@item Commodore CDXL @tab @tab X | |
| 135 | + @tab Amiga CD video format | |
| 134 | 136 | @item Core Audio Format @tab @tab X |
| 135 | 137 | @tab Apple Core Audio Format |
| 136 | 138 | @item CRC testing format @tab X @tab |
| @@ -435,6 +437,8 @@ following image formats are supported: · 298 unmodified lines | ||
| 435 | 437 | @tab fourcc: CSCD |
| 436 | 438 | @item CD+G @tab @tab X |
| 437 | 439 | @tab Video codec for CD+G karaoke disks |
| 440 | +@item CDXL @tab @tab X | |
| 441 | + @tab Amiga CD video codec | |
| 438 | 442 | @item Chinese AVS video @tab E @tab X |
| 439 | 443 | @tab AVS1-P2, JiZhun profile, encoding through external library libxavs |
| 440 | 444 | @item Delphine Software International CIN video @tab @tab X |
| @@ -102,6 +102,7 @@ OBJS-$(CONFIG_C93_DECODER) += c93.o · 101 unmodified lines | ||
| 102 | 102 | OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \ |
| 103 | 103 | mpeg12data.o mpegvideo.o |
| 104 | 104 | OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o |
| 105 | +OBJS-$(CONFIG_CDXL_DECODER) += cdxl.o | |
| 105 | 106 | OBJS-$(CONFIG_CINEPAK_DECODER) += cinepak.o |
| 106 | 107 | OBJS-$(CONFIG_CLJR_DECODER) += cljr.o |
| 107 | 108 | OBJS-$(CONFIG_CLJR_ENCODER) += cljr.o |
| @@ -86,6 +86,7 @@ void avcodec_register_all(void) · 85 unmodified lines | ||
| 86 | 86 | REGISTER_DECODER (C93, c93); |
| 87 | 87 | REGISTER_DECODER (CAVS, cavs); |
| 88 | 88 | REGISTER_DECODER (CDGRAPHICS, cdgraphics); |
| 89 | + REGISTER_DECODER (CDXL, cdxl); | |
| 89 | 90 | REGISTER_DECODER (CINEPAK, cinepak); |
| 90 | 91 | REGISTER_ENCDEC (CLJR, cljr); |
| 91 | 92 | REGISTER_DECODER (CSCD, cscd); |
| @@ -244,6 +244,7 @@ enum CodecID { · 243 unmodified lines | ||
| 244 | 244 | CODEC_ID_DXTORY, |
| 245 | 245 | CODEC_ID_V410, |
| 246 | 246 | CODEC_ID_XWD, |
| 247 | + CODEC_ID_CDXL, | |
| 247 | 248 | |
| 248 | 249 | /* various PCM "codecs" */ |
| 249 | 250 | CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs |
| @@ -0,0 +1,278 @@ | ||
| 1 | +/* | |
| 2 | + * CDXL video decoder | |
| 3 | + * Copyright (c) 2011-2012 Paul B Mahol | |
| 4 | + * | |
| 5 | + * This file is part of Libav. | |
| 6 | + * | |
| 7 | + * Libav is free software; you can redistribute it and/or | |
| 8 | + * modify it under the terms of the GNU Lesser General Public | |
| 9 | + * License as published by the Free Software Foundation; either | |
| 10 | + * version 2.1 of the License, or (at your option) any later version. | |
| 11 | + * | |
| 12 | + * Libav is distributed in the hope that it will be useful, | |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 | + * Lesser General Public License for more details. | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU Lesser General Public | |
| 18 | + * License along with Libav; if not, write to the Free Software | |
| 19 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 | + */ | |
| 21 | + | |
| 22 | +#include "libavutil/intreadwrite.h" | |
| 23 | +#include "libavutil/imgutils.h" | |
| 24 | +#include "avcodec.h" | |
| 25 | +#include "get_bits.h" | |
| 26 | + | |
| 27 | +typedef struct { | |
| 28 | + AVCodecContext *avctx; | |
| 29 | + AVFrame frame; | |
| 30 | + int bpp; | |
| 31 | + const uint8_t *palette; | |
| 32 | + int palette_size; | |
| 33 | + const uint8_t *video; | |
| 34 | + int video_size; | |
| 35 | + uint8_t *new_video; | |
| 36 | + int new_video_size; | |
| 37 | +} CDXLVideoContext; | |
| 38 | + | |
| 39 | +static av_cold int cdxl_decode_init(AVCodecContext *avctx) | |
| 40 | +{ | |
| 41 | + CDXLVideoContext *c = avctx->priv_data; | |
| 42 | + | |
| 43 | + avcodec_get_frame_defaults(&c->frame); | |
| 44 | + c->new_video_size = 0; | |
| 45 | + c->avctx = avctx; | |
| 46 | + | |
| 47 | + return 0; | |
| 48 | +} | |
| 49 | + | |
| 50 | +static void import_palette(CDXLVideoContext *c, uint32_t *new_palette) | |
| 51 | +{ | |
| 52 | + int i; | |
| 53 | + | |
| 54 | + for (i = 0; i < c->palette_size / 2; i++) { | |
| 55 | + unsigned rgb = AV_RB16(&c->palette[i * 2]); | |
| 56 | + unsigned r = ((rgb >> 8) & 0xF) * 0x11; | |
| 57 | + unsigned g = ((rgb >> 4) & 0xF) * 0x11; | |
| 58 | + unsigned b = (rgb & 0xF) * 0x11; | |
| 59 | + AV_WN32(&new_palette[i], (r << 16) | (g << 8) | b); | |
| 60 | + } | |
| 61 | +} | |
| 62 | + | |
| 63 | +static void bitplanar2chunky(CDXLVideoContext *c, int width, | |
| 64 | + int linesize, uint8_t *out) | |
| 65 | +{ | |
| 66 | + GetBitContext gb; | |
| 67 | + int x, y, plane; | |
| 68 | + | |
| 69 | + init_get_bits(&gb, c->video, c->video_size * 8); | |
| 70 | + memset(out, 0, linesize * c->avctx->height); | |
| 71 | + for (plane = 0; plane < c->bpp; plane++) | |
| 72 | + for (y = 0; y < c->avctx->height; y++) | |
| 73 | + for (x = 0; x < width; x++) | |
| 74 | + out[linesize * y + x] |= get_bits1(&gb) << plane; | |
| 75 | +} | |
| 76 | + | |
| 77 | +static void cdxl_decode_rgb(CDXLVideoContext *c) | |
| 78 | +{ | |
| 79 | + uint32_t *new_palette = (uint32_t *)c->frame.data[1]; | |
| 80 | + int padded_width = FFALIGN(c->avctx->width, 16); | |
| 81 | + | |
| 82 | + import_palette(c, new_palette); | |
| 83 | + bitplanar2chunky(c, padded_width, c->frame.linesize[0], c->frame.data[0]); | |
| 84 | +} | |
| 85 | + | |
| 86 | +static void cdxl_decode_ham6(CDXLVideoContext *c) | |
| 87 | +{ | |
| 88 | + AVCodecContext *avctx = c->avctx; | |
| 89 | + uint32_t new_palette[16], r, g, b; | |
| 90 | + uint8_t *ptr, *out, index, op; | |
| 91 | + int x, y; | |
| 92 | + | |
| 93 | + ptr = c->new_video; | |
| 94 | + out = c->frame.data[0]; | |
| 95 | + | |
| 96 | + import_palette(c, new_palette); | |
| 97 | + bitplanar2chunky(c, avctx->width, avctx->width, c->new_video); | |
| 98 | + | |
| 99 | + for (y = 0; y < avctx->height; y++) { | |
| 100 | + r = new_palette[0] & 0xFF0000; | |
| 101 | + g = new_palette[0] & 0xFF00; | |
| 102 | + b = new_palette[0] & 0xFF; | |
| 103 | + for (x = 0; x < avctx->width; x++) { | |
| 104 | + index = *ptr++; | |
| 105 | + op = index >> 4; | |
| 106 | + index &= 15; | |
| 107 | + switch (op) { | |
| 108 | + case 0: | |
| 109 | + r = new_palette[index] & 0xFF0000; | |
| 110 | + g = new_palette[index] & 0xFF00; | |
| 111 | + b = new_palette[index] & 0xFF; | |
| 112 | + break; | |
| 113 | + case 1: | |
| 114 | + b = index * 0x11; | |
| 115 | + break; | |
| 116 | + case 2: | |
| 117 | + r = index * 0x11 << 16; | |
| 118 | + break; | |
| 119 | + case 3: | |
| 120 | + g = index * 0x11 << 8; | |
| 121 | + break; | |
| 122 | + } | |
| 123 | + AV_WN32(out + x * 3, r | g | b); | |
| 124 | + } | |
| 125 | + out += c->frame.linesize[0]; | |
| 126 | + } | |
| 127 | +} | |
| 128 | + | |
| 129 | +static void cdxl_decode_ham8(CDXLVideoContext *c) | |
| 130 | +{ | |
| 131 | + AVCodecContext *avctx = c->avctx; | |
| 132 | + uint32_t new_palette[64], r, g, b; | |
| 133 | + uint8_t *ptr, *out, index, op; | |
| 134 | + int x, y; | |
| 135 | + | |
| 136 | + ptr = c->new_video; | |
| 137 | + out = c->frame.data[0]; | |
| 138 | + | |
| 139 | + import_palette(c, new_palette); | |
| 140 | + bitplanar2chunky(c, avctx->width, avctx->width, c->new_video); | |
| 141 | + | |
| 142 | + for (y = 0; y < avctx->height; y++) { | |
| 143 | + r = new_palette[0] & 0xFF0000; | |
| 144 | + g = new_palette[0] & 0xFF00; | |
| 145 | + b = new_palette[0] & 0xFF; | |
| 146 | + for (x = 0; x < avctx->width; x++) { | |
| 147 | + index = *ptr++; | |
| 148 | + op = index >> 6; | |
| 149 | + index &= 63; | |
| 150 | + switch (op) { | |
| 151 | + case 0: | |
| 152 | + r = new_palette[index] & 0xFF0000; | |
| 153 | + g = new_palette[index] & 0xFF00; | |
| 154 | + b = new_palette[index] & 0xFF; | |
| 155 | + break; | |
| 156 | + case 1: | |
| 157 | + b = (index << 2) | (b & 3); | |
| 158 | + break; | |
| 159 | + case 2: | |
| 160 | + r = (index << 18) | (r & (3 << 16)); | |
| 161 | + break; | |
| 162 | + case 3: | |
| 163 | + g = (index << 10) | (g & (3 << 8)); | |
| 164 | + break; | |
| 165 | + } | |
| 166 | + AV_WN32(out + x * 3, r | g | b); | |
| 167 | + } | |
| 168 | + out += c->frame.linesize[0]; | |
| 169 | + } | |
| 170 | +} | |
| 171 | + | |
| 172 | +static int cdxl_decode_frame(AVCodecContext *avctx, void *data, | |
| 173 | + int *data_size, AVPacket *pkt) | |
| 174 | +{ | |
| 175 | + CDXLVideoContext *c = avctx->priv_data; | |
| 176 | + AVFrame * const p = &c->frame; | |
| 177 | + int ret, w, h, encoding, format, buf_size = pkt->size; | |
| 178 | + const uint8_t *buf = pkt->data; | |
| 179 | + | |
| 180 | + if (buf_size < 32) | |
| 181 | + return AVERROR_INVALIDDATA; | |
| 182 | + encoding = buf[1] & 7; | |
| 183 | + format = buf[1] & 0xE0; | |
| 184 | + w = AV_RB16(&buf[14]); | |
| 185 | + h = AV_RB16(&buf[16]); | |
| 186 | + c->bpp = buf[19]; | |
| 187 | + c->palette_size = AV_RB16(&buf[20]); | |
| 188 | + c->palette = buf + 32; | |
| 189 | + c->video = c->palette + c->palette_size; | |
| 190 | + c->video_size = buf_size - c->palette_size - 32; | |
| 191 | + | |
| 192 | + if (c->palette_size > 512) | |
| 193 | + return AVERROR_INVALIDDATA; | |
| 194 | + if (buf_size < c->palette_size + 32) | |
| 195 | + return AVERROR_INVALIDDATA; | |
| 196 | + if (c->bpp < 1) | |
| 197 | + return AVERROR_INVALIDDATA; | |
| 198 | + if (c->bpp > 8) { | |
| 199 | + av_log_ask_for_sample(avctx, "unsupported pixel size: %d\n", c->bpp); | |
| 200 | + return AVERROR_PATCHWELCOME; | |
| 201 | + } | |
| 202 | + if (format) { | |
| 203 | + av_log_ask_for_sample(avctx, "unsupported pixel format: %d\n", format); | |
| 204 | + return AVERROR_PATCHWELCOME; | |
| 205 | + } | |
| 206 | + | |
| 207 | + if ((ret = av_image_check_size(w, h, 0, avctx)) < 0) | |
| 208 | + return ret; | |
| 209 | + if (w != avctx->width || h != avctx->height) | |
| 210 | + avcodec_set_dimensions(avctx, w, h); | |
| 211 | + | |
| 212 | + if (encoding == 0) { | |
| 213 | + if (c->video_size < FFALIGN(avctx->width, 16) * | |
| 214 | + avctx->height * c->bpp / 8) | |
| 215 | + return AVERROR_INVALIDDATA; | |
| 216 | + avctx->pix_fmt = PIX_FMT_PAL8; | |
| 217 | + } else if (encoding == 1 && (c->bpp == 6 || c->bpp == 8)) { | |
| 218 | + if (c->palette_size != (1 << (c->bpp - 1))) | |
| 219 | + return AVERROR_INVALIDDATA; | |
| 220 | + if (c->video_size < avctx->width * avctx->height * c->bpp / 8) | |
| 221 | + return AVERROR_INVALIDDATA; | |
| 222 | + avctx->pix_fmt = PIX_FMT_BGR24; | |
| 223 | + } else { | |
| 224 | + av_log_ask_for_sample(avctx, "unsupported encoding %d and bpp %d\n", | |
| 225 | + encoding, c->bpp); | |
| 226 | + return AVERROR_PATCHWELCOME; | |
| 227 | + } | |
| 228 | + | |
| 229 | + if (p->data[0]) | |
| 230 | + avctx->release_buffer(avctx, p); | |
| 231 | + | |
| 232 | + p->reference = 0; | |
| 233 | + if ((ret = avctx->get_buffer(avctx, p)) < 0) { | |
| 234 | + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
| 235 | + return ret; | |
| 236 | + } | |
| 237 | + p->pict_type = AV_PICTURE_TYPE_I; | |
| 238 | + | |
| 239 | + if (encoding) { | |
| 240 | + av_fast_padded_malloc(&c->new_video, &c->new_video_size, | |
| 241 | + h * w + FF_INPUT_BUFFER_PADDING_SIZE); | |
| 242 | + if (!c->new_video) | |
| 243 | + return AVERROR(ENOMEM); | |
| 244 | + if (c->bpp == 8) | |
| 245 | + cdxl_decode_ham8(c); | |
| 246 | + else | |
| 247 | + cdxl_decode_ham6(c); | |
| 248 | + } else { | |
| 249 | + cdxl_decode_rgb(c); | |
| 250 | + } | |
| 251 | + *data_size = sizeof(AVFrame); | |
| 252 | + *(AVFrame*)data = c->frame; | |
| 253 | + | |
| 254 | + return buf_size; | |
| 255 | +} | |
| 256 | + | |
| 257 | +static av_cold int cdxl_decode_end(AVCodecContext *avctx) | |
| 258 | +{ | |
| 259 | + CDXLVideoContext *c = avctx->priv_data; | |
| 260 | + | |
| 261 | + av_free(c->new_video); | |
| 262 | + if (c->frame.data[0]) | |
| 263 | + avctx->release_buffer(avctx, &c->frame); | |
| 264 | + | |
| 265 | + return 0; | |
| 266 | +} | |
| 267 | + | |
| 268 | +AVCodec ff_cdxl_decoder = { | |
| 269 | + .name = "cdxl", | |
| 270 | + .type = AVMEDIA_TYPE_VIDEO, | |
| 271 | + .id = CODEC_ID_CDXL, | |
| 272 | + .priv_data_size = sizeof(CDXLVideoContext), | |
| 273 | + .init = cdxl_decode_init, | |
| 274 | + .close = cdxl_decode_end, | |
| 275 | + .decode = cdxl_decode_frame, | |
| 276 | + .capabilities = CODEC_CAP_DR1, | |
| 277 | + .long_name = NULL_IF_CONFIG_SMALL("Commodore CDXL video"), | |
| 278 | +}; | |
| @@ -21,7 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | #define AVCODEC_VERSION_H |
| 22 | 22 | |
| 23 | 23 | #define LIBAVCODEC_VERSION_MAJOR 54 |
| 24 | −#define LIBAVCODEC_VERSION_MINOR 0 | |
| 24 | +#define LIBAVCODEC_VERSION_MINOR 1 | |
| 25 | 25 | #define LIBAVCODEC_VERSION_MICRO 0 |
| 26 | 26 | |
| 27 | 27 | #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ |
| @@ -55,6 +55,7 @@ OBJS-$(CONFIG_CAF_DEMUXER) += cafdec.o caf.o mov.o mov_chan.o \ · 54 unmodified lines | ||
| 55 | 55 | OBJS-$(CONFIG_CAVSVIDEO_DEMUXER) += cavsvideodec.o rawdec.o |
| 56 | 56 | OBJS-$(CONFIG_CAVSVIDEO_MUXER) += rawenc.o |
| 57 | 57 | OBJS-$(CONFIG_CDG_DEMUXER) += cdg.o |
| 58 | +OBJS-$(CONFIG_CDXL_DEMUXER) += cdxl.o | |
| 58 | 59 | OBJS-$(CONFIG_CRC_MUXER) += crcenc.o |
| 59 | 60 | OBJS-$(CONFIG_DAUD_DEMUXER) += daud.o |
| 60 | 61 | OBJS-$(CONFIG_DAUD_MUXER) += daud.o |
| @@ -76,6 +76,7 @@ void av_register_all(void) · 75 unmodified lines | ||
| 76 | 76 | REGISTER_DEMUXER (CAF, caf); |
| 77 | 77 | REGISTER_MUXDEMUX (CAVSVIDEO, cavsvideo); |
| 78 | 78 | REGISTER_DEMUXER (CDG, cdg); |
| 79 | + REGISTER_DEMUXER (CDXL, cdxl); | |
| 79 | 80 | REGISTER_MUXER (CRC, crc); |
| 80 | 81 | REGISTER_MUXDEMUX (DAUD, daud); |
| 81 | 82 | REGISTER_DEMUXER (DFA, dfa); |
| @@ -0,0 +1,170 @@ | ||
| 1 | +/* | |
| 2 | + * CDXL demuxer | |
| 3 | + * Copyright (c) 2011-2012 Paul B Mahol | |
| 4 | + * | |
| 5 | + * This file is part of Libav. | |
| 6 | + * | |
| 7 | + * Libav is free software; you can redistribute it and/or | |
| 8 | + * modify it under the terms of the GNU Lesser General Public | |
| 9 | + * License as published by the Free Software Foundation; either | |
| 10 | + * version 2.1 of the License, or (at your option) any later version. | |
| 11 | + * | |
| 12 | + * Libav is distributed in the hope that it will be useful, | |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 | + * Lesser General Public License for more details. | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU Lesser General Public | |
| 18 | + * License along with Libav; if not, write to the Free Software | |
| 19 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 | + */ | |
| 21 | + | |
| 22 | +#include "libavutil/intreadwrite.h" | |
| 23 | +#include "libavutil/parseutils.h" | |
| 24 | +#include "libavutil/opt.h" | |
| 25 | +#include "avformat.h" | |
| 26 | +#include "internal.h" | |
| 27 | + | |
| 28 | +#define CDXL_HEADER_SIZE 32 | |
| 29 | + | |
| 30 | +typedef struct CDXLDemuxContext { | |
| 31 | + AVClass *class; | |
| 32 | + int sample_rate; | |
| 33 | + char *framerate; | |
| 34 | + AVRational fps; | |
| 35 | + int read_chunk; | |
| 36 | + uint8_t header[CDXL_HEADER_SIZE]; | |
| 37 | + int video_stream_index; | |
| 38 | + int audio_stream_index; | |
| 39 | +} CDXLDemuxContext; | |
| 40 | + | |
| 41 | +static int cdxl_read_header(AVFormatContext *s) | |
| 42 | +{ | |
| 43 | + CDXLDemuxContext *cdxl = s->priv_data; | |
| 44 | + int ret; | |
| 45 | + | |
| 46 | + if ((ret = av_parse_video_rate(&cdxl->fps, cdxl->framerate)) < 0) { | |
| 47 | + av_log(s, AV_LOG_ERROR, | |
| 48 | + "Could not parse framerate: %s.\n", cdxl->framerate); | |
| 49 | + return ret; | |
| 50 | + } | |
| 51 | + | |
| 52 | + cdxl->read_chunk = 0; | |
| 53 | + cdxl->video_stream_index = -1; | |
| 54 | + cdxl->audio_stream_index = -1; | |
| 55 | + | |
| 56 | + s->ctx_flags |= AVFMTCTX_NOHEADER; | |
| 57 | + | |
| 58 | + return 0; | |
| 59 | +} | |
| 60 | + | |
| 61 | +static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt) | |
| 62 | +{ | |
| 63 | + CDXLDemuxContext *cdxl = s->priv_data; | |
| 64 | + AVIOContext *pb = s->pb; | |
| 65 | + uint32_t current_size; | |
| 66 | + uint16_t audio_size, palette_size; | |
| 67 | + int32_t video_size; | |
| 68 | + int64_t pos; | |
| 69 | + int ret; | |
| 70 | + | |
| 71 | + if (pb->eof_reached) | |
| 72 | + return AVERROR_EOF; | |
| 73 | + | |
| 74 | + pos = avio_tell(pb); | |
| 75 | + if (!cdxl->read_chunk && | |
| 76 | + avio_read(pb, cdxl->header, CDXL_HEADER_SIZE) != CDXL_HEADER_SIZE) | |
| 77 | + return AVERROR_EOF; | |
| 78 | + if (cdxl->header[0] != 1) { | |
| 79 | + av_log(s, AV_LOG_ERROR, "non-standard cdxl file\n"); | |
| 80 | + return AVERROR_INVALIDDATA; | |
| 81 | + } | |
| 82 | + | |
| 83 | + current_size = AV_RB32(&cdxl->header[2]); | |
| 84 | + palette_size = AV_RB16(&cdxl->header[20]); | |
| 85 | + audio_size = AV_RB16(&cdxl->header[22]); | |
| 86 | + | |
| 87 | + if (palette_size > 512) | |
| 88 | + return AVERROR_INVALIDDATA; | |
| 89 | + if (current_size < audio_size + palette_size + CDXL_HEADER_SIZE) | |
| 90 | + return AVERROR_INVALIDDATA; | |
| 91 | + video_size = current_size - audio_size - CDXL_HEADER_SIZE; | |
| 92 | + | |
| 93 | + if (cdxl->read_chunk && audio_size) { | |
| 94 | + if (cdxl->audio_stream_index == -1) { | |
| 95 | + AVStream *st = avformat_new_stream(s, NULL); | |
| 96 | + if (!st) | |
| 97 | + return AVERROR(ENOMEM); | |
| 98 | + | |
| 99 | + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; | |
| 100 | + st->codec->codec_tag = 0; | |
| 101 | + st->codec->codec_id = CODEC_ID_PCM_S8; | |
| 102 | + st->codec->channels = cdxl->header[1] & 0x10 ? 2 : 1; | |
| 103 | + st->codec->sample_rate = cdxl->sample_rate; | |
| 104 | + cdxl->audio_stream_index = st->index; | |
| 105 | + avpriv_set_pts_info(st, 32, 1, cdxl->sample_rate); | |
| 106 | + } | |
| 107 | + | |
| 108 | + ret = av_get_packet(pb, pkt, audio_size); | |
| 109 | + if (ret < 0) | |
| 110 | + return ret; | |
| 111 | + pkt->stream_index = cdxl->audio_stream_index; | |
| 112 | + pkt->pos = pos; | |
| 113 | + pkt->duration = audio_size; | |
| 114 | + cdxl->read_chunk = 0; | |
| 115 | + } else { | |
| 116 | + if (cdxl->video_stream_index == -1) { | |
| 117 | + AVStream *st = avformat_new_stream(s, NULL); | |
| 118 | + if (!st) | |
| 119 | + return AVERROR(ENOMEM); | |
| 120 | + | |
| 121 | + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; | |
| 122 | + st->codec->codec_tag = 0; | |
| 123 | + st->codec->codec_id = CODEC_ID_CDXL; | |
| 124 | + st->codec->width = AV_RB16(&cdxl->header[14]); | |
| 125 | + st->codec->height = AV_RB16(&cdxl->header[16]); | |
| 126 | + cdxl->video_stream_index = st->index; | |
| 127 | + avpriv_set_pts_info(st, 63, cdxl->fps.den, cdxl->fps.num); | |
| 128 | + } | |
| 129 | + | |
| 130 | + if (av_new_packet(pkt, video_size + CDXL_HEADER_SIZE) < 0) | |
| 131 | + return AVERROR(ENOMEM); | |
| 132 | + memcpy(pkt->data, cdxl->header, CDXL_HEADER_SIZE); | |
| 133 | + ret = avio_read(pb, pkt->data + CDXL_HEADER_SIZE, video_size); | |
| 134 | + if (ret < 0) { | |
| 135 | + av_free_packet(pkt); | |
| 136 | + return ret; | |
| 137 | + } | |
| 138 | + pkt->stream_index = cdxl->video_stream_index; | |
| 139 | + pkt->flags |= AV_PKT_FLAG_KEY; | |
| 140 | + pkt->pos = pos; | |
| 141 | + cdxl->read_chunk = audio_size; | |
| 142 | + } | |
| 143 | + | |
| 144 | + return ret; | |
| 145 | +} | |
| 146 | + | |
| 147 | +#define OFFSET(x) offsetof(CDXLDemuxContext, x) | |
| 148 | +static const AVOption cdxl_options[] = { | |
| 149 | + { "sample_rate", "", OFFSET(sample_rate), AV_OPT_TYPE_INT, { .dbl = 11025 }, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, | |
| 150 | + { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, { .str = "10" }, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, | |
| 151 | + { NULL }, | |
| 152 | +}; | |
| 153 | + | |
| 154 | +static const AVClass cdxl_demuxer_class = { | |
| 155 | + .class_name = "CDXL demuxer", | |
| 156 | + .item_name = av_default_item_name, | |
| 157 | + .option = cdxl_options, | |
| 158 | + .version = LIBAVUTIL_VERSION_INT, | |
| 159 | +}; | |
| 160 | + | |
| 161 | +AVInputFormat ff_cdxl_demuxer = { | |
| 162 | + .name = "cdxl", | |
| 163 | + .long_name = NULL_IF_CONFIG_SMALL("Commodore CDXL video format"), | |
| 164 | + .priv_data_size = sizeof(CDXLDemuxContext), | |
| 165 | + .read_header = cdxl_read_header, | |
| 166 | + .read_packet = cdxl_read_packet, | |
| 167 | + .extensions = "cdxl,xl", | |
| 168 | + .flags = AVFMT_GENERIC_INDEX, | |
| 169 | + .priv_class = &cdxl_demuxer_class, | |
| 170 | +}; | |
| @@ -30,7 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | #include "libavutil/avutil.h" |
| 31 | 31 | |
| 32 | 32 | #define LIBAVFORMAT_VERSION_MAJOR 54 |
| 33 | −#define LIBAVFORMAT_VERSION_MINOR 0 | |
| 33 | +#define LIBAVFORMAT_VERSION_MINOR 1 | |
| 34 | 34 | #define LIBAVFORMAT_VERSION_MICRO 0 |
| 35 | 35 | |
| 36 | 36 | #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ |