diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 576ec5f005..e4113da808 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -112,6 +112,7 @@ OBJS-$(CONFIG_ATRAC1_DECODER) += atrac1.o atrac.o OBJS-$(CONFIG_ATRAC3_DECODER) += atrac3.o atrac.o OBJS-$(CONFIG_AURA_DECODER) += cyuv.o OBJS-$(CONFIG_AURA2_DECODER) += aura.o +OBJS-$(CONFIG_AVRP_DECODER) += avrndec.o OBJS-$(CONFIG_AVRP_DECODER) += r210dec.o OBJS-$(CONFIG_AVRP_ENCODER) += r210enc.o OBJS-$(CONFIG_AVS_DECODER) += avs.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 4a247c4a67..00f44a57a6 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -81,6 +81,7 @@ void avcodec_register_all(void) REGISTER_DECODER (AURA, aura); REGISTER_DECODER (AURA2, aura2); REGISTER_ENCDEC (AVRP, avrp); + REGISTER_DECODER (AVRN, avrn); REGISTER_DECODER (AVS, avs); REGISTER_ENCDEC (AVUI, avui); REGISTER_ENCDEC (AYUV, ayuv); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 1115caf23d..c3cde347d3 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -276,6 +276,7 @@ enum AVCodecID { AV_CODEC_ID_YUV4 = MKBETAG('Y','U','V','4'), AV_CODEC_ID_SANM = MKBETAG('S','A','N','M'), AV_CODEC_ID_PAF_VIDEO = MKBETAG('P','A','F','V'), + AV_CODEC_ID_AVRN = MKBETAG('A','V','R','n'), /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/avrndec.c b/libavcodec/avrndec.c new file mode 100644 index 0000000000..b173c6dcf4 --- /dev/null +++ b/libavcodec/avrndec.c @@ -0,0 +1,129 @@ +/* + * AVRn decoder + * Copyright (c) 2012 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "mjpeg.h" +#include "mjpegdec.h" + +typedef struct { + MJpegDecodeContext mjpeg_ctx; + AVFrame frame; + int is_mjpeg; + int interlace; //FIXME use frame.interlaced_frame + int tff; +} AVRnContext; + +static av_cold int init(AVCodecContext *avctx) +{ + AVRnContext *a = avctx->priv_data; + + // Support "Resolution 1:1" for Avid AVI Codec + a->is_mjpeg = avctx->extradata_size < 31 || memcmp(&avctx->extradata[28], "1:1", 3); + + if(a->is_mjpeg) + return ff_mjpeg_decode_init(avctx); + + if(avctx->width <= 0 || avctx->height <= 0) + return -1; + + avcodec_get_frame_defaults(&a->frame); + avctx->pix_fmt = PIX_FMT_UYVY422; + + if(avctx->extradata_size >= 9 && avctx->extradata[4]+28 < avctx->extradata_size) { + int ndx = avctx->extradata[4] + 4; + a->interlace = !memcmp(avctx->extradata + ndx, "1:1(", 4); + if(a->interlace) { + a->tff = avctx->extradata[ndx + 24] == 1; + } + } + + return 0; +} + +static av_cold void end(AVCodecContext *avctx) +{ + AVRnContext *a = avctx->priv_data; + AVFrame *p = &a->frame; + + if(p->data[0]) + avctx->release_buffer(avctx, p); + + if(a->is_mjpeg) + ff_mjpeg_decode_end(avctx); +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) +{ + AVRnContext *a = avctx->priv_data; + AVFrame *p = &a->frame; + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + int y; + + if(a->is_mjpeg) + return ff_mjpeg_decode_frame(avctx, data, data_size, avpkt); + + if(p->data[0]) + avctx->release_buffer(avctx, p); + + if(buf_size < 2*avctx->width * avctx->height) { + av_log(avctx, AV_LOG_ERROR, "packet too small\n"); + return AVERROR_INVALIDDATA; + } + + if(avctx->get_buffer(avctx, p) < 0){ + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + return -1; + } + p->pict_type= AV_PICTURE_TYPE_I; + p->key_frame= 1; + + if(a->interlace) { + int true_height = buf_size / (2*avctx->width); + buf += (true_height - avctx->height)*avctx->width; + for(y = 0; y < avctx->height-1; y+=2) { + memcpy(p->data[0] + (y+ a->tff)*p->linesize[0], buf , 2*avctx->width); + memcpy(p->data[0] + (y+!a->tff)*p->linesize[0], buf + avctx->width*true_height+4, 2*avctx->width); + buf += 2*avctx->width; + } + } else { + for(y = 0; y < avctx->height; y++) { + memcpy(p->data[0] + y*p->linesize[0], buf, 2*avctx->width); + buf += 2*avctx->width; + } + } + + *(AVFrame*)data = a->frame; + *data_size = sizeof(AVFrame); + return buf_size; +} + +AVCodec ff_avrn_decoder = { + .name = "AVRn", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AVRN, + .priv_data_size = sizeof(AVRnContext), + .init = init, + .close = end, + .decode = decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("AVRn"), +}; + diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 607eaab84a..68e07bbd41 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1175,6 +1175,12 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "paf_video", .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Video"), }, + { + .id = AV_CODEC_ID_AVRN, + .type = AVMEDIA_TYPE_VIDEO, + .name = "AVRn", + .long_name = NULL_IF_CONFIG_SMALL("AVRn"), + }, /* various PCM "codecs" */ { diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c index 9e2fbaafbe..9920e7875e 100644 --- a/libavcodec/rawdec.c +++ b/libavcodec/rawdec.c @@ -39,7 +39,6 @@ typedef struct RawVideoContext { unsigned char * buffer; /* block of memory for holding one frame */ int length; /* number of bytes in buffer */ int flip; - int interlace; AVFrame pic; ///< AVCodecContext.coded_frame int tff; } RawVideoContext; @@ -131,17 +130,6 @@ static av_cold int raw_init_decoder(AVCodecContext *avctx) avctx->codec_tag == MKTAG(3, 0, 0, 0) || avctx->codec_tag == MKTAG('W','R','A','W')) context->flip=1; - if(avctx->extradata_size >= 9 && avctx->extradata[4]+28 < avctx->extradata_size && !context->buffer && avctx->pix_fmt == PIX_FMT_UYVY422) { - int ndx = avctx->extradata[4] + 4; - context->interlace = !memcmp(avctx->extradata + ndx, "1:1(", 4); - if(context->interlace) { - context->buffer = av_malloc(context->length); - if (!context->buffer) - return AVERROR(ENOMEM); - context->tff = avctx->extradata[ndx + 24] == 1; - } - } - return 0; } @@ -185,41 +173,23 @@ static int raw_decode(AVCodecContext *avctx, if (context->buffer) { int i; uint8_t *dst = context->buffer; - if(avctx->pix_fmt == PIX_FMT_PAL8){ - buf_size = context->length - AVPALETTE_SIZE; - if (avctx->bits_per_coded_sample == 4){ - for(i=0; 2*i+1 < buf_size && isize; i++){ - dst[2*i+0]= buf[i]>>4; - dst[2*i+1]= buf[i]&15; - } - linesize_align = 8; - } else { - av_assert0(avctx->bits_per_coded_sample == 2); - for(i=0; 4*i+3 < buf_size && isize; i++){ - dst[4*i+0]= buf[i]>>6; - dst[4*i+1]= buf[i]>>4&3; - dst[4*i+2]= buf[i]>>2&3; - dst[4*i+3]= buf[i] &3; - } - linesize_align = 16; + buf_size = context->length - AVPALETTE_SIZE; + if (avctx->bits_per_coded_sample == 4){ + for(i=0; 2*i+1 < buf_size && isize; i++){ + dst[2*i+0]= buf[i]>>4; + dst[2*i+1]= buf[i]&15; } - } else if(context->interlace && avctx->pix_fmt == PIX_FMT_UYVY422) { - int x, y; - int true_height = buf_size / (2*avctx->width); - int tff = !!context->tff; - av_assert0(avctx->height * avctx->width * 2 == context->length); - if (buf_size < context->length) { - av_log(avctx, AV_LOG_ERROR, "Invalid buffer size, packet size %d < context length %d\n", buf_size, context->length); - return AVERROR(EINVAL); + linesize_align = 8; + } else { + av_assert0(avctx->bits_per_coded_sample == 2); + for(i=0; 4*i+3 < buf_size && isize; i++){ + dst[4*i+0]= buf[i]>>6; + dst[4*i+1]= buf[i]>>4&3; + dst[4*i+2]= buf[i]>>2&3; + dst[4*i+3]= buf[i] &3; } - buf += (true_height - avctx->height)*avctx->width; - for(y = 0; y < avctx->height-1; y+=2) { - memcpy(dst + (y+ tff)*2*avctx->width, buf , 2*avctx->width); - memcpy(dst + (y+!tff)*2*avctx->width, buf + avctx->width*true_height+4, 2*avctx->width); - buf += 2*avctx->width; - } - }else - av_assert0(0); + linesize_align = 16; + } buf= dst; } diff --git a/libavformat/avidec.c b/libavformat/avidec.c index d3bb8d85f9..a70a0113a0 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -635,11 +635,6 @@ static int avi_read_header(AVFormatContext *s) st->codec->codec_tag = tag1; st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag1); st->need_parsing = AVSTREAM_PARSE_HEADERS; // This is needed to get the pict type which is necessary for generating correct pts. - // Support "Resolution 1:1" for Avid AVI Codec - if(tag1 == MKTAG('A', 'V', 'R', 'n') && - st->codec->extradata_size >= 31 && - !memcmp(&st->codec->extradata[28], "1:1", 3)) - st->codec->codec_id = AV_CODEC_ID_RAWVIDEO; if(st->codec->codec_tag==0 && st->codec->height > 0 && st->codec->extradata_size < 1U<<30){ st->codec->extradata_size+= 9; diff --git a/libavformat/riff.c b/libavformat/riff.c index 2152c0fbdb..77dc797157 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -154,7 +154,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_MJPEG, MKTAG('M', 'J', 'L', 'S') }, /* JPEG-LS custom FOURCC for avi - decoder */ { AV_CODEC_ID_MJPEG, MKTAG('j', 'p', 'e', 'g') }, { AV_CODEC_ID_MJPEG, MKTAG('I', 'J', 'P', 'G') }, - { AV_CODEC_ID_MJPEG, MKTAG('A', 'V', 'R', 'n') }, + { AV_CODEC_ID_AVRN, MKTAG('A', 'V', 'R', 'n') }, { AV_CODEC_ID_MJPEG, MKTAG('A', 'C', 'D', 'V') }, { AV_CODEC_ID_MJPEG, MKTAG('Q', 'I', 'V', 'G') }, { AV_CODEC_ID_MJPEG, MKTAG('S', 'L', 'M', 'J') }, /* SL M-JPEG */