return 0;
}
- static void flip(AVCodecContext *avctx, AVPicture *picture)
+ static void flip(AVCodecContext *avctx, AVFrame *frame)
{
- picture->data[0] += picture->linesize[0] * (avctx->height - 1);
- picture->linesize[0] *= -1;
+ frame->data[0] += frame->linesize[0] * (avctx->height - 1);
+ frame->linesize[0] *= -1;
}
+/*
+ * Scale sample to 16-bit resolution
+ */
+#define SCALE16(x, bits) (((x) << (16 - (bits))) | ((x) >> (2 * (bits) - 16)))
+
+/**
+ * Scale buffer to 16 bits per coded sample resolution
+ */
+#define MKSCALE16(name, r16, w16) \
+static void name(AVCodecContext *avctx, uint8_t * dst, const uint8_t *buf, int buf_size, int packed) \
+{ \
+ int i; \
+ if (!packed) { \
+ for (i = 0; i + 1 < buf_size; i += 2) \
+ w16(dst + i, SCALE16(r16(buf + i), avctx->bits_per_coded_sample)); \
+ } else { \
+ GetBitContext gb; \
+ init_get_bits(&gb, buf, buf_size * 8); \
+ for (i = 0; i < avctx->width * avctx->height; i++) { \
+ int sample = get_bits(&gb, avctx->bits_per_coded_sample); \
+ w16(dst + i*2, SCALE16(sample, avctx->bits_per_coded_sample)); \
+ } \
+ } \
+}
+
+MKSCALE16(scale16be, AV_RB16, AV_WB16)
+MKSCALE16(scale16le, AV_RL16, AV_WL16)
+
static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame,
AVPacket *avpkt)
{
RawVideoContext *context = avctx->priv_data;
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
- int need_copy = !avpkt->buf || context->is_2_4_bpp || context->is_yuv2;
- int res;
+ int linesize_align = 4;
+ int res, len;
+ int need_copy;
AVFrame *frame = data;
- AVPicture *picture = data;
- context->frame_size = avpicture_get_size(avctx->pix_fmt,
- FFALIGN(avctx->width, 16),
- avctx->height);
+ if ((avctx->bits_per_coded_sample == 4 || avctx->bits_per_coded_sample == 2) &&
+ avctx->pix_fmt == AV_PIX_FMT_PAL8 &&
+ (!avctx->codec_tag || avctx->codec_tag == MKTAG('r','a','w',' '))) {
+ context->is_2_4_bpp = 1;
- context->frame_size = avpicture_get_size(avctx->pix_fmt, avctx->width,
- avctx->height);
++ context->frame_size = av_image_get_buffer_size(avctx->pix_fmt,
++ FFALIGN(avctx->width, 16),
++ avctx->height, 1);
+ } else {
+ context->is_lt_16bpp = av_get_bits_per_pixel(desc) == 16 && avctx->bits_per_coded_sample && avctx->bits_per_coded_sample < 16;
++ context->frame_size = av_image_get_buffer_size(avctx->pix_fmt, avctx->width,
++ avctx->height, 1);
+ }
+ if (context->frame_size < 0)
+ return context->frame_size;
+
+ need_copy = !avpkt->buf || context->is_2_4_bpp || context->is_yuv2 || context->is_lt_16bpp;
+
frame->pict_type = AV_PICTURE_TYPE_I;
frame->key_frame = 1;
avctx->codec_tag == MKTAG('A', 'V', 'u', 'p'))
buf += buf_size - context->frame_size;
- if ((res = avpicture_fill(picture, buf, avctx->pix_fmt,
- avctx->width, avctx->height)) < 0) {
+ len = context->frame_size - (avctx->pix_fmt==AV_PIX_FMT_PAL8 ? AVPALETTE_SIZE : 0);
+ if (buf_size < len && (avctx->codec_tag & 0xFFFFFF) != MKTAG('B','I','T', 0)) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid buffer size, packet size %d < expected frame_size %d\n", buf_size, len);
+ av_buffer_unref(&frame->buf[0]);
+ return AVERROR(EINVAL);
+ }
+
- avctx->width, avctx->height, 1)) < 0)
+ if ((res = av_image_fill_arrays(frame->data, frame->linesize,
+ buf, avctx->pix_fmt,
++ avctx->width, avctx->height, 1)) < 0) {
+ av_buffer_unref(&frame->buf[0]);
return res;
+ }
if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE,
avctx->codec_tag == MKTAG('Y', 'V', '1', '6') ||
avctx->codec_tag == MKTAG('Y', 'V', '2', '4') ||
avctx->codec_tag == MKTAG('Y', 'V', 'U', '9'))
- FFSWAP(uint8_t *, picture->data[1], picture->data[2]);
+ FFSWAP(uint8_t *, frame->data[1], frame->data[2]);
- picture->data[1] = picture->data[1] + (avctx->width+1)*(avctx->height+1) -avctx->width*avctx->height;
- picture->data[2] = picture->data[2] + ((avctx->width+1)*(avctx->height+1) -avctx->width*avctx->height)*5/4;
+ if (avctx->codec_tag == AV_RL32("I420") && (avctx->width+1)*(avctx->height+1) * 3/2 == buf_size) {
++ frame->data[1] = frame->data[1] + (avctx->width+1)*(avctx->height+1) -avctx->width*avctx->height;
++ frame->data[2] = frame->data[2] + ((avctx->width+1)*(avctx->height+1) -avctx->width*avctx->height)*5/4;
+ }
+
if (avctx->codec_tag == AV_RL32("yuv2") &&
avctx->pix_fmt == AV_PIX_FMT_YUYV422) {
int x, y;