Signed-off-by: Paul B Mahol <onemda@gmail.com> Signed-off-by: Diego Biurrun <diego@biurrun.de>tags/n0.11
| @@ -6,6 +6,7 @@ version <next>: | |||||
| - XWD encoder and decoder | - XWD encoder and decoder | ||||
| - Support for fragmentation in the mov/mp4 muxer | - Support for fragmentation in the mov/mp4 muxer | ||||
| - ISMV (Smooth Streaming) muxer | - ISMV (Smooth Streaming) muxer | ||||
| - CDXL demuxer and decoder | |||||
| version 0.8: | version 0.8: | ||||
| @@ -131,6 +131,8 @@ library: | |||||
| @tab Multimedia format used by Delphine Software games. | @tab Multimedia format used by Delphine Software games. | ||||
| @item CD+G @tab @tab X | @item CD+G @tab @tab X | ||||
| @tab Video format used by CD+G karaoke disks | @tab Video format used by CD+G karaoke disks | ||||
| @item Commodore CDXL @tab @tab X | |||||
| @tab Amiga CD video format | |||||
| @item Core Audio Format @tab @tab X | @item Core Audio Format @tab @tab X | ||||
| @tab Apple Core Audio Format | @tab Apple Core Audio Format | ||||
| @item CRC testing format @tab X @tab | @item CRC testing format @tab X @tab | ||||
| @@ -435,6 +437,8 @@ following image formats are supported: | |||||
| @tab fourcc: CSCD | @tab fourcc: CSCD | ||||
| @item CD+G @tab @tab X | @item CD+G @tab @tab X | ||||
| @tab Video codec for CD+G karaoke disks | @tab Video codec for CD+G karaoke disks | ||||
| @item CDXL @tab @tab X | |||||
| @tab Amiga CD video codec | |||||
| @item Chinese AVS video @tab E @tab X | @item Chinese AVS video @tab E @tab X | ||||
| @tab AVS1-P2, JiZhun profile, encoding through external library libxavs | @tab AVS1-P2, JiZhun profile, encoding through external library libxavs | ||||
| @item Delphine Software International CIN video @tab @tab X | @item Delphine Software International CIN video @tab @tab X | ||||
| @@ -102,6 +102,7 @@ OBJS-$(CONFIG_C93_DECODER) += c93.o | |||||
| OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \ | OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \ | ||||
| mpeg12data.o mpegvideo.o | mpeg12data.o mpegvideo.o | ||||
| OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o | OBJS-$(CONFIG_CDGRAPHICS_DECODER) += cdgraphics.o | ||||
| OBJS-$(CONFIG_CDXL_DECODER) += cdxl.o | |||||
| OBJS-$(CONFIG_CINEPAK_DECODER) += cinepak.o | OBJS-$(CONFIG_CINEPAK_DECODER) += cinepak.o | ||||
| OBJS-$(CONFIG_CLJR_DECODER) += cljr.o | OBJS-$(CONFIG_CLJR_DECODER) += cljr.o | ||||
| OBJS-$(CONFIG_CLJR_ENCODER) += cljr.o | OBJS-$(CONFIG_CLJR_ENCODER) += cljr.o | ||||
| @@ -86,6 +86,7 @@ void avcodec_register_all(void) | |||||
| REGISTER_DECODER (C93, c93); | REGISTER_DECODER (C93, c93); | ||||
| REGISTER_DECODER (CAVS, cavs); | REGISTER_DECODER (CAVS, cavs); | ||||
| REGISTER_DECODER (CDGRAPHICS, cdgraphics); | REGISTER_DECODER (CDGRAPHICS, cdgraphics); | ||||
| REGISTER_DECODER (CDXL, cdxl); | |||||
| REGISTER_DECODER (CINEPAK, cinepak); | REGISTER_DECODER (CINEPAK, cinepak); | ||||
| REGISTER_ENCDEC (CLJR, cljr); | REGISTER_ENCDEC (CLJR, cljr); | ||||
| REGISTER_DECODER (CSCD, cscd); | REGISTER_DECODER (CSCD, cscd); | ||||
| @@ -244,6 +244,7 @@ enum CodecID { | |||||
| CODEC_ID_DXTORY, | CODEC_ID_DXTORY, | ||||
| CODEC_ID_V410, | CODEC_ID_V410, | ||||
| CODEC_ID_XWD, | CODEC_ID_XWD, | ||||
| CODEC_ID_CDXL, | |||||
| /* various PCM "codecs" */ | /* various PCM "codecs" */ | ||||
| CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs | CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs | ||||
| @@ -0,0 +1,278 @@ | |||||
| /* | |||||
| * CDXL video decoder | |||||
| * Copyright (c) 2011-2012 Paul B Mahol | |||||
| * | |||||
| * This file is part of Libav. | |||||
| * | |||||
| * Libav is free software; you can redistribute it and/or | |||||
| * modify it under the terms of the GNU Lesser General Public | |||||
| * License as published by the Free Software Foundation; either | |||||
| * version 2.1 of the License, or (at your option) any later version. | |||||
| * | |||||
| * Libav is distributed in the hope that it will be useful, | |||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||||
| * Lesser General Public License for more details. | |||||
| * | |||||
| * You should have received a copy of the GNU Lesser General Public | |||||
| * License along with Libav; if not, write to the Free Software | |||||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||||
| */ | |||||
| #include "libavutil/intreadwrite.h" | |||||
| #include "libavutil/imgutils.h" | |||||
| #include "avcodec.h" | |||||
| #include "get_bits.h" | |||||
| typedef struct { | |||||
| AVCodecContext *avctx; | |||||
| AVFrame frame; | |||||
| int bpp; | |||||
| const uint8_t *palette; | |||||
| int palette_size; | |||||
| const uint8_t *video; | |||||
| int video_size; | |||||
| uint8_t *new_video; | |||||
| int new_video_size; | |||||
| } CDXLVideoContext; | |||||
| static av_cold int cdxl_decode_init(AVCodecContext *avctx) | |||||
| { | |||||
| CDXLVideoContext *c = avctx->priv_data; | |||||
| avcodec_get_frame_defaults(&c->frame); | |||||
| c->new_video_size = 0; | |||||
| c->avctx = avctx; | |||||
| return 0; | |||||
| } | |||||
| 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], (r << 16) | (g << 8) | b); | |||||
| } | |||||
| } | |||||
| static void bitplanar2chunky(CDXLVideoContext *c, int width, | |||||
| int linesize, uint8_t *out) | |||||
| { | |||||
| GetBitContext gb; | |||||
| int x, y, plane; | |||||
| init_get_bits(&gb, c->video, c->video_size * 8); | |||||
| memset(out, 0, linesize * c->avctx->height); | |||||
| for (plane = 0; plane < c->bpp; plane++) | |||||
| for (y = 0; y < c->avctx->height; y++) | |||||
| for (x = 0; x < width; x++) | |||||
| out[linesize * y + x] |= get_bits1(&gb) << plane; | |||||
| } | |||||
| static void cdxl_decode_rgb(CDXLVideoContext *c) | |||||
| { | |||||
| uint32_t *new_palette = (uint32_t *)c->frame.data[1]; | |||||
| int padded_width = FFALIGN(c->avctx->width, 16); | |||||
| import_palette(c, new_palette); | |||||
| bitplanar2chunky(c, padded_width, c->frame.linesize[0], c->frame.data[0]); | |||||
| } | |||||
| static void cdxl_decode_ham6(CDXLVideoContext *c) | |||||
| { | |||||
| AVCodecContext *avctx = c->avctx; | |||||
| uint32_t new_palette[16], r, g, b; | |||||
| uint8_t *ptr, *out, index, op; | |||||
| int x, y; | |||||
| ptr = c->new_video; | |||||
| out = c->frame.data[0]; | |||||
| import_palette(c, new_palette); | |||||
| bitplanar2chunky(c, avctx->width, avctx->width, c->new_video); | |||||
| for (y = 0; y < avctx->height; y++) { | |||||
| r = new_palette[0] & 0xFF0000; | |||||
| g = new_palette[0] & 0xFF00; | |||||
| b = new_palette[0] & 0xFF; | |||||
| for (x = 0; x < avctx->width; x++) { | |||||
| index = *ptr++; | |||||
| op = index >> 4; | |||||
| index &= 15; | |||||
| switch (op) { | |||||
| case 0: | |||||
| r = new_palette[index] & 0xFF0000; | |||||
| g = new_palette[index] & 0xFF00; | |||||
| b = new_palette[index] & 0xFF; | |||||
| break; | |||||
| case 1: | |||||
| b = index * 0x11; | |||||
| break; | |||||
| case 2: | |||||
| r = index * 0x11 << 16; | |||||
| break; | |||||
| case 3: | |||||
| g = index * 0x11 << 8; | |||||
| break; | |||||
| } | |||||
| AV_WN32(out + x * 3, r | g | b); | |||||
| } | |||||
| out += c->frame.linesize[0]; | |||||
| } | |||||
| } | |||||
| static void cdxl_decode_ham8(CDXLVideoContext *c) | |||||
| { | |||||
| AVCodecContext *avctx = c->avctx; | |||||
| uint32_t new_palette[64], r, g, b; | |||||
| uint8_t *ptr, *out, index, op; | |||||
| int x, y; | |||||
| ptr = c->new_video; | |||||
| out = c->frame.data[0]; | |||||
| import_palette(c, new_palette); | |||||
| bitplanar2chunky(c, avctx->width, avctx->width, c->new_video); | |||||
| for (y = 0; y < avctx->height; y++) { | |||||
| r = new_palette[0] & 0xFF0000; | |||||
| g = new_palette[0] & 0xFF00; | |||||
| b = new_palette[0] & 0xFF; | |||||
| for (x = 0; x < avctx->width; x++) { | |||||
| index = *ptr++; | |||||
| op = index >> 6; | |||||
| index &= 63; | |||||
| switch (op) { | |||||
| case 0: | |||||
| r = new_palette[index] & 0xFF0000; | |||||
| g = new_palette[index] & 0xFF00; | |||||
| b = new_palette[index] & 0xFF; | |||||
| break; | |||||
| case 1: | |||||
| b = (index << 2) | (b & 3); | |||||
| break; | |||||
| case 2: | |||||
| r = (index << 18) | (r & (3 << 16)); | |||||
| break; | |||||
| case 3: | |||||
| g = (index << 10) | (g & (3 << 8)); | |||||
| break; | |||||
| } | |||||
| AV_WN32(out + x * 3, r | g | b); | |||||
| } | |||||
| out += c->frame.linesize[0]; | |||||
| } | |||||
| } | |||||
| static int cdxl_decode_frame(AVCodecContext *avctx, void *data, | |||||
| int *data_size, AVPacket *pkt) | |||||
| { | |||||
| CDXLVideoContext *c = avctx->priv_data; | |||||
| AVFrame * const p = &c->frame; | |||||
| int ret, w, h, encoding, format, buf_size = pkt->size; | |||||
| const uint8_t *buf = pkt->data; | |||||
| if (buf_size < 32) | |||||
| return AVERROR_INVALIDDATA; | |||||
| encoding = buf[1] & 7; | |||||
| format = buf[1] & 0xE0; | |||||
| w = AV_RB16(&buf[14]); | |||||
| h = AV_RB16(&buf[16]); | |||||
| c->bpp = buf[19]; | |||||
| c->palette_size = AV_RB16(&buf[20]); | |||||
| c->palette = buf + 32; | |||||
| c->video = c->palette + c->palette_size; | |||||
| c->video_size = buf_size - c->palette_size - 32; | |||||
| if (c->palette_size > 512) | |||||
| return AVERROR_INVALIDDATA; | |||||
| if (buf_size < c->palette_size + 32) | |||||
| return AVERROR_INVALIDDATA; | |||||
| if (c->bpp < 1) | |||||
| return AVERROR_INVALIDDATA; | |||||
| if (c->bpp > 8) { | |||||
| av_log_ask_for_sample(avctx, "unsupported pixel size: %d\n", c->bpp); | |||||
| return AVERROR_PATCHWELCOME; | |||||
| } | |||||
| if (format) { | |||||
| av_log_ask_for_sample(avctx, "unsupported pixel format: %d\n", format); | |||||
| return AVERROR_PATCHWELCOME; | |||||
| } | |||||
| if ((ret = av_image_check_size(w, h, 0, avctx)) < 0) | |||||
| return ret; | |||||
| if (w != avctx->width || h != avctx->height) | |||||
| avcodec_set_dimensions(avctx, w, h); | |||||
| if (encoding == 0) { | |||||
| if (c->video_size < FFALIGN(avctx->width, 16) * | |||||
| avctx->height * c->bpp / 8) | |||||
| return AVERROR_INVALIDDATA; | |||||
| avctx->pix_fmt = PIX_FMT_PAL8; | |||||
| } else if (encoding == 1 && (c->bpp == 6 || c->bpp == 8)) { | |||||
| if (c->palette_size != (1 << (c->bpp - 1))) | |||||
| return AVERROR_INVALIDDATA; | |||||
| if (c->video_size < avctx->width * avctx->height * c->bpp / 8) | |||||
| return AVERROR_INVALIDDATA; | |||||
| avctx->pix_fmt = PIX_FMT_BGR24; | |||||
| } else { | |||||
| av_log_ask_for_sample(avctx, "unsupported encoding %d and bpp %d\n", | |||||
| encoding, c->bpp); | |||||
| return AVERROR_PATCHWELCOME; | |||||
| } | |||||
| if (p->data[0]) | |||||
| avctx->release_buffer(avctx, p); | |||||
| p->reference = 0; | |||||
| if ((ret = avctx->get_buffer(avctx, p)) < 0) { | |||||
| av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |||||
| return ret; | |||||
| } | |||||
| p->pict_type = AV_PICTURE_TYPE_I; | |||||
| if (encoding) { | |||||
| av_fast_padded_malloc(&c->new_video, &c->new_video_size, | |||||
| h * w + FF_INPUT_BUFFER_PADDING_SIZE); | |||||
| if (!c->new_video) | |||||
| return AVERROR(ENOMEM); | |||||
| if (c->bpp == 8) | |||||
| cdxl_decode_ham8(c); | |||||
| else | |||||
| cdxl_decode_ham6(c); | |||||
| } else { | |||||
| cdxl_decode_rgb(c); | |||||
| } | |||||
| *data_size = sizeof(AVFrame); | |||||
| *(AVFrame*)data = c->frame; | |||||
| return buf_size; | |||||
| } | |||||
| static av_cold int cdxl_decode_end(AVCodecContext *avctx) | |||||
| { | |||||
| CDXLVideoContext *c = avctx->priv_data; | |||||
| av_free(c->new_video); | |||||
| if (c->frame.data[0]) | |||||
| avctx->release_buffer(avctx, &c->frame); | |||||
| return 0; | |||||
| } | |||||
| AVCodec ff_cdxl_decoder = { | |||||
| .name = "cdxl", | |||||
| .type = AVMEDIA_TYPE_VIDEO, | |||||
| .id = CODEC_ID_CDXL, | |||||
| .priv_data_size = sizeof(CDXLVideoContext), | |||||
| .init = cdxl_decode_init, | |||||
| .close = cdxl_decode_end, | |||||
| .decode = cdxl_decode_frame, | |||||
| .capabilities = CODEC_CAP_DR1, | |||||
| .long_name = NULL_IF_CONFIG_SMALL("Commodore CDXL video"), | |||||
| }; | |||||
| @@ -21,7 +21,7 @@ | |||||
| #define AVCODEC_VERSION_H | #define AVCODEC_VERSION_H | ||||
| #define LIBAVCODEC_VERSION_MAJOR 54 | #define LIBAVCODEC_VERSION_MAJOR 54 | ||||
| #define LIBAVCODEC_VERSION_MINOR 0 | |||||
| #define LIBAVCODEC_VERSION_MINOR 1 | |||||
| #define LIBAVCODEC_VERSION_MICRO 0 | #define LIBAVCODEC_VERSION_MICRO 0 | ||||
| #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | #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 \ | |||||
| OBJS-$(CONFIG_CAVSVIDEO_DEMUXER) += cavsvideodec.o rawdec.o | OBJS-$(CONFIG_CAVSVIDEO_DEMUXER) += cavsvideodec.o rawdec.o | ||||
| OBJS-$(CONFIG_CAVSVIDEO_MUXER) += rawenc.o | OBJS-$(CONFIG_CAVSVIDEO_MUXER) += rawenc.o | ||||
| OBJS-$(CONFIG_CDG_DEMUXER) += cdg.o | OBJS-$(CONFIG_CDG_DEMUXER) += cdg.o | ||||
| OBJS-$(CONFIG_CDXL_DEMUXER) += cdxl.o | |||||
| OBJS-$(CONFIG_CRC_MUXER) += crcenc.o | OBJS-$(CONFIG_CRC_MUXER) += crcenc.o | ||||
| OBJS-$(CONFIG_DAUD_DEMUXER) += daud.o | OBJS-$(CONFIG_DAUD_DEMUXER) += daud.o | ||||
| OBJS-$(CONFIG_DAUD_MUXER) += daud.o | OBJS-$(CONFIG_DAUD_MUXER) += daud.o | ||||
| @@ -76,6 +76,7 @@ void av_register_all(void) | |||||
| REGISTER_DEMUXER (CAF, caf); | REGISTER_DEMUXER (CAF, caf); | ||||
| REGISTER_MUXDEMUX (CAVSVIDEO, cavsvideo); | REGISTER_MUXDEMUX (CAVSVIDEO, cavsvideo); | ||||
| REGISTER_DEMUXER (CDG, cdg); | REGISTER_DEMUXER (CDG, cdg); | ||||
| REGISTER_DEMUXER (CDXL, cdxl); | |||||
| REGISTER_MUXER (CRC, crc); | REGISTER_MUXER (CRC, crc); | ||||
| REGISTER_MUXDEMUX (DAUD, daud); | REGISTER_MUXDEMUX (DAUD, daud); | ||||
| REGISTER_DEMUXER (DFA, dfa); | REGISTER_DEMUXER (DFA, dfa); | ||||
| @@ -0,0 +1,170 @@ | |||||
| /* | |||||
| * CDXL demuxer | |||||
| * Copyright (c) 2011-2012 Paul B Mahol | |||||
| * | |||||
| * This file is part of Libav. | |||||
| * | |||||
| * Libav is free software; you can redistribute it and/or | |||||
| * modify it under the terms of the GNU Lesser General Public | |||||
| * License as published by the Free Software Foundation; either | |||||
| * version 2.1 of the License, or (at your option) any later version. | |||||
| * | |||||
| * Libav is distributed in the hope that it will be useful, | |||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||||
| * Lesser General Public License for more details. | |||||
| * | |||||
| * You should have received a copy of the GNU Lesser General Public | |||||
| * License along with Libav; if not, write to the Free Software | |||||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||||
| */ | |||||
| #include "libavutil/intreadwrite.h" | |||||
| #include "libavutil/parseutils.h" | |||||
| #include "libavutil/opt.h" | |||||
| #include "avformat.h" | |||||
| #include "internal.h" | |||||
| #define CDXL_HEADER_SIZE 32 | |||||
| typedef struct CDXLDemuxContext { | |||||
| AVClass *class; | |||||
| int sample_rate; | |||||
| char *framerate; | |||||
| AVRational fps; | |||||
| int read_chunk; | |||||
| uint8_t header[CDXL_HEADER_SIZE]; | |||||
| int video_stream_index; | |||||
| int audio_stream_index; | |||||
| } CDXLDemuxContext; | |||||
| static int cdxl_read_header(AVFormatContext *s) | |||||
| { | |||||
| CDXLDemuxContext *cdxl = s->priv_data; | |||||
| int ret; | |||||
| if ((ret = av_parse_video_rate(&cdxl->fps, cdxl->framerate)) < 0) { | |||||
| av_log(s, AV_LOG_ERROR, | |||||
| "Could not parse framerate: %s.\n", cdxl->framerate); | |||||
| return ret; | |||||
| } | |||||
| cdxl->read_chunk = 0; | |||||
| cdxl->video_stream_index = -1; | |||||
| cdxl->audio_stream_index = -1; | |||||
| s->ctx_flags |= AVFMTCTX_NOHEADER; | |||||
| return 0; | |||||
| } | |||||
| static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt) | |||||
| { | |||||
| CDXLDemuxContext *cdxl = s->priv_data; | |||||
| AVIOContext *pb = s->pb; | |||||
| uint32_t current_size; | |||||
| uint16_t audio_size, palette_size; | |||||
| int32_t video_size; | |||||
| int64_t pos; | |||||
| int ret; | |||||
| if (pb->eof_reached) | |||||
| 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->header[0] != 1) { | |||||
| av_log(s, AV_LOG_ERROR, "non-standard cdxl file\n"); | |||||
| return AVERROR_INVALIDDATA; | |||||
| } | |||||
| current_size = AV_RB32(&cdxl->header[2]); | |||||
| palette_size = AV_RB16(&cdxl->header[20]); | |||||
| audio_size = AV_RB16(&cdxl->header[22]); | |||||
| if (palette_size > 512) | |||||
| return AVERROR_INVALIDDATA; | |||||
| if (current_size < audio_size + palette_size + CDXL_HEADER_SIZE) | |||||
| return AVERROR_INVALIDDATA; | |||||
| video_size = current_size - audio_size - CDXL_HEADER_SIZE; | |||||
| if (cdxl->read_chunk && audio_size) { | |||||
| if (cdxl->audio_stream_index == -1) { | |||||
| AVStream *st = avformat_new_stream(s, NULL); | |||||
| if (!st) | |||||
| return AVERROR(ENOMEM); | |||||
| st->codec->codec_type = AVMEDIA_TYPE_AUDIO; | |||||
| st->codec->codec_tag = 0; | |||||
| st->codec->codec_id = CODEC_ID_PCM_S8; | |||||
| st->codec->channels = cdxl->header[1] & 0x10 ? 2 : 1; | |||||
| st->codec->sample_rate = cdxl->sample_rate; | |||||
| cdxl->audio_stream_index = st->index; | |||||
| avpriv_set_pts_info(st, 32, 1, cdxl->sample_rate); | |||||
| } | |||||
| 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; | |||||
| cdxl->read_chunk = 0; | |||||
| } else { | |||||
| if (cdxl->video_stream_index == -1) { | |||||
| AVStream *st = avformat_new_stream(s, NULL); | |||||
| if (!st) | |||||
| return AVERROR(ENOMEM); | |||||
| st->codec->codec_type = AVMEDIA_TYPE_VIDEO; | |||||
| st->codec->codec_tag = 0; | |||||
| st->codec->codec_id = CODEC_ID_CDXL; | |||||
| st->codec->width = AV_RB16(&cdxl->header[14]); | |||||
| st->codec->height = AV_RB16(&cdxl->header[16]); | |||||
| cdxl->video_stream_index = st->index; | |||||
| avpriv_set_pts_info(st, 63, cdxl->fps.den, cdxl->fps.num); | |||||
| } | |||||
| if (av_new_packet(pkt, video_size + CDXL_HEADER_SIZE) < 0) | |||||
| return AVERROR(ENOMEM); | |||||
| memcpy(pkt->data, cdxl->header, CDXL_HEADER_SIZE); | |||||
| ret = avio_read(pb, pkt->data + CDXL_HEADER_SIZE, video_size); | |||||
| if (ret < 0) { | |||||
| av_free_packet(pkt); | |||||
| return ret; | |||||
| } | |||||
| pkt->stream_index = cdxl->video_stream_index; | |||||
| pkt->flags |= AV_PKT_FLAG_KEY; | |||||
| pkt->pos = pos; | |||||
| cdxl->read_chunk = audio_size; | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| #define OFFSET(x) offsetof(CDXLDemuxContext, x) | |||||
| static const AVOption cdxl_options[] = { | |||||
| { "sample_rate", "", OFFSET(sample_rate), AV_OPT_TYPE_INT, { .dbl = 11025 }, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, | |||||
| { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, { .str = "10" }, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, | |||||
| { NULL }, | |||||
| }; | |||||
| static const AVClass cdxl_demuxer_class = { | |||||
| .class_name = "CDXL demuxer", | |||||
| .item_name = av_default_item_name, | |||||
| .option = cdxl_options, | |||||
| .version = LIBAVUTIL_VERSION_INT, | |||||
| }; | |||||
| AVInputFormat ff_cdxl_demuxer = { | |||||
| .name = "cdxl", | |||||
| .long_name = NULL_IF_CONFIG_SMALL("Commodore CDXL video format"), | |||||
| .priv_data_size = sizeof(CDXLDemuxContext), | |||||
| .read_header = cdxl_read_header, | |||||
| .read_packet = cdxl_read_packet, | |||||
| .extensions = "cdxl,xl", | |||||
| .flags = AVFMT_GENERIC_INDEX, | |||||
| .priv_class = &cdxl_demuxer_class, | |||||
| }; | |||||
| @@ -30,7 +30,7 @@ | |||||
| #include "libavutil/avutil.h" | #include "libavutil/avutil.h" | ||||
| #define LIBAVFORMAT_VERSION_MAJOR 54 | #define LIBAVFORMAT_VERSION_MAJOR 54 | ||||
| #define LIBAVFORMAT_VERSION_MINOR 0 | |||||
| #define LIBAVFORMAT_VERSION_MINOR 1 | |||||
| #define LIBAVFORMAT_VERSION_MICRO 0 | #define LIBAVFORMAT_VERSION_MICRO 0 | ||||
| #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | ||||