Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2009 Michael Niedermayer <[email protected]> |
| 3 | * |
| 4 | * This file is part of FFmpeg. |
| 5 | * |
| 6 | * FFmpeg is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU Lesser General Public |
| 8 | * License as published by the Free Software Foundation; either |
| 9 | * version 2.1 of the License, or (at your option) any later version. |
| 10 | * |
| 11 | * FFmpeg is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * Lesser General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU Lesser General Public |
| 17 | * License along with FFmpeg; if not, write to the Free Software |
| 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 19 | */ |
| 20 | |
| 21 | #include "avcodec.h" |
Andreas Rheinhardt | a688f3c | 2022-03-16 17:18:28 | [diff] [blame] | 22 | #include "codec_internal.h" |
Andreas Rheinhardt | 66b691f | 2022-08-24 19:28:16 | [diff] [blame] | 23 | #include "decode.h" |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 24 | #include "libavutil/bswap.h" |
Martin Storsjö | 1d9c2dc | 2012-08-06 13:49:32 | [diff] [blame] | 25 | #include "libavutil/internal.h" |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 26 | |
| 27 | static av_cold int decode_init(AVCodecContext *avctx) |
| 28 | { |
Anton Khirnov | de16f08 | 2012-11-17 14:39:18 | [diff] [blame] | 29 | if (avctx->width & 1) { |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 30 | av_log(avctx, AV_LOG_ERROR, "v210x needs even width\n"); |
Anton Khirnov | 6689474 | 2012-11-17 14:34:17 | [diff] [blame] | 31 | return AVERROR(EINVAL); |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 32 | } |
Anton Khirnov | de16f08 | 2012-11-17 14:39:18 | [diff] [blame] | 33 | avctx->pix_fmt = AV_PIX_FMT_YUV422P16; |
| 34 | avctx->bits_per_raw_sample = 10; |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 35 | |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 36 | return 0; |
| 37 | } |
| 38 | |
Andreas Rheinhardt | ce7dbd0 | 2022-03-30 19:33:24 | [diff] [blame] | 39 | static int decode_frame(AVCodecContext *avctx, AVFrame *pic, |
| 40 | int *got_frame, AVPacket *avpkt) |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 41 | { |
Anton Khirnov | de16f08 | 2012-11-17 14:39:18 | [diff] [blame] | 42 | const uint32_t *src = (const uint32_t *)avpkt->data; |
Anton Khirnov | de16f08 | 2012-11-17 14:39:18 | [diff] [blame] | 43 | int width = avctx->width; |
| 44 | int y = 0; |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 45 | uint16_t *ydst, *udst, *vdst, *yend; |
Anton Khirnov | 6689474 | 2012-11-17 14:34:17 | [diff] [blame] | 46 | int ret; |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 47 | |
Anton Khirnov | de16f08 | 2012-11-17 14:39:18 | [diff] [blame] | 48 | if (avpkt->size < avctx->width * avctx->height * 8 / 3) { |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 49 | av_log(avctx, AV_LOG_ERROR, "Packet too small\n"); |
Anton Khirnov | 6689474 | 2012-11-17 14:34:17 | [diff] [blame] | 50 | return AVERROR_INVALIDDATA; |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 51 | } |
| 52 | |
Anton Khirnov | de16f08 | 2012-11-17 14:39:18 | [diff] [blame] | 53 | if (avpkt->size > avctx->width * avctx->height * 8 / 3) { |
Diego Biurrun | 6d97484 | 2013-03-13 20:17:05 | [diff] [blame] | 54 | avpriv_request_sample(avctx, "(Probably) padded data"); |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 55 | } |
| 56 | |
Anton Khirnov | 759001c | 2012-11-21 20:34:46 | [diff] [blame] | 57 | if ((ret = ff_get_buffer(avctx, pic, 0)) < 0) |
Anton Khirnov | 6689474 | 2012-11-17 14:34:17 | [diff] [blame] | 58 | return ret; |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 59 | |
Anton Khirnov | de16f08 | 2012-11-17 14:39:18 | [diff] [blame] | 60 | ydst = (uint16_t *)pic->data[0]; |
| 61 | udst = (uint16_t *)pic->data[1]; |
| 62 | vdst = (uint16_t *)pic->data[2]; |
| 63 | yend = ydst + width; |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 64 | |
Anton Khirnov | de16f08 | 2012-11-17 14:39:18 | [diff] [blame] | 65 | for (;;) { |
| 66 | uint32_t v = av_be2ne32(*src++); |
| 67 | *udst++ = (v >> 16) & 0xFFC0; |
| 68 | *ydst++ = (v >> 6 ) & 0xFFC0; |
| 69 | *vdst++ = (v << 4 ) & 0xFFC0; |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 70 | |
Anton Khirnov | de16f08 | 2012-11-17 14:39:18 | [diff] [blame] | 71 | v = av_be2ne32(*src++); |
| 72 | *ydst++ = (v >> 16) & 0xFFC0; |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 73 | |
Anton Khirnov | de16f08 | 2012-11-17 14:39:18 | [diff] [blame] | 74 | if (ydst >= yend) { |
| 75 | ydst += pic->linesize[0] / 2 - width; |
| 76 | udst += pic->linesize[1] / 2 - width / 2; |
| 77 | vdst += pic->linesize[2] / 2 - width / 2; |
| 78 | yend = ydst + width; |
| 79 | if (++y >= avctx->height) |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 80 | break; |
| 81 | } |
| 82 | |
Anton Khirnov | de16f08 | 2012-11-17 14:39:18 | [diff] [blame] | 83 | *udst++ = (v >> 6 ) & 0xFFC0; |
| 84 | *ydst++ = (v << 4 ) & 0xFFC0; |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 85 | |
Anton Khirnov | de16f08 | 2012-11-17 14:39:18 | [diff] [blame] | 86 | v = av_be2ne32(*src++); |
| 87 | *vdst++ = (v >> 16) & 0xFFC0; |
| 88 | *ydst++ = (v >> 6 ) & 0xFFC0; |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 89 | |
Anton Khirnov | de16f08 | 2012-11-17 14:39:18 | [diff] [blame] | 90 | if (ydst >= yend) { |
| 91 | ydst += pic->linesize[0] / 2 - width; |
| 92 | udst += pic->linesize[1] / 2 - width / 2; |
| 93 | vdst += pic->linesize[2] / 2 - width / 2; |
| 94 | yend = ydst + width; |
| 95 | if (++y >= avctx->height) |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 96 | break; |
| 97 | } |
| 98 | |
Anton Khirnov | de16f08 | 2012-11-17 14:39:18 | [diff] [blame] | 99 | *udst++ = (v << 4 ) & 0xFFC0; |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 100 | |
Anton Khirnov | de16f08 | 2012-11-17 14:39:18 | [diff] [blame] | 101 | v = av_be2ne32(*src++); |
| 102 | *ydst++ = (v >> 16) & 0xFFC0; |
| 103 | *vdst++ = (v >> 6 ) & 0xFFC0; |
| 104 | *ydst++ = (v << 4 ) & 0xFFC0; |
| 105 | if (ydst >= yend) { |
| 106 | ydst += pic->linesize[0] / 2 - width; |
| 107 | udst += pic->linesize[1] / 2 - width / 2; |
| 108 | vdst += pic->linesize[2] / 2 - width / 2; |
| 109 | yend = ydst + width; |
| 110 | if (++y >= avctx->height) |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 111 | break; |
| 112 | } |
| 113 | } |
| 114 | |
Anton Khirnov | df9b956 | 2012-11-13 18:35:22 | [diff] [blame] | 115 | *got_frame = 1; |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 116 | |
| 117 | return avpkt->size; |
| 118 | } |
| 119 | |
Andreas Rheinhardt | 20f9727 | 2022-03-16 20:09:54 | [diff] [blame] | 120 | const FFCodec ff_v210x_decoder = { |
| 121 | .p.name = "v210x", |
Andreas Rheinhardt | 48286d4 | 2022-08-29 11:38:02 | [diff] [blame] | 122 | CODEC_LONG_NAME("Uncompressed 4:2:2 10-bit"), |
Andreas Rheinhardt | 20f9727 | 2022-03-16 20:09:54 | [diff] [blame] | 123 | .p.type = AVMEDIA_TYPE_VIDEO, |
| 124 | .p.id = AV_CODEC_ID_V210X, |
Anton Khirnov | ec6402b | 2011-07-17 10:54:31 | [diff] [blame] | 125 | .init = decode_init, |
Andreas Rheinhardt | 4243da4 | 2022-03-30 21:28:24 | [diff] [blame] | 126 | FF_CODEC_DECODE_CB(decode_frame), |
Andreas Rheinhardt | 20f9727 | 2022-03-16 20:09:54 | [diff] [blame] | 127 | .p.capabilities = AV_CODEC_CAP_DR1, |
Michael Niedermayer | 97f9214 | 2009-04-22 01:50:15 | [diff] [blame] | 128 | }; |