FFmpeg
v210dec.c
Go to the documentation of this file.
1 /*
2  * V210 decoder
3  *
4  * Copyright (C) 2009 Michael Niedermayer <michaelni@gmx.at>
5  * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
6  *
7  * This file is part of FFmpeg.
8  *
9  * FFmpeg is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * FFmpeg is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with FFmpeg; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 #include "avcodec.h"
25 #include "codec_internal.h"
26 #include "v210dec.h"
27 #include "v210dec_init.h"
28 #include "libavutil/bswap.h"
29 #include "libavutil/imgutils.h"
30 #include "libavutil/internal.h"
31 #include "libavutil/intreadwrite.h"
32 #include "libavutil/mem.h"
33 #include "thread.h"
34 
35 typedef struct ThreadData {
36  AVFrame *frame;
37  const uint8_t *buf;
38  int stride;
39 } ThreadData;
40 
42 {
43  V210DecContext *s = avctx->priv_data;
44 
46  avctx->bits_per_raw_sample = 10;
47 
48  s->thread_count = av_clip(avctx->thread_count, 1, avctx->height/4);
49  s->aligned_input = 0;
51 
52  return 0;
53 }
54 
55 static void decode_row(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, const int width,
56  void (*unpack_frame)(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width))
57 {
58  uint32_t val;
59  int w = (FFMAX(0, width - 12) / 12) * 12;
60 
61  unpack_frame(src, y, u, v, w);
62 
63  y += w;
64  u += w >> 1;
65  v += w >> 1;
66  src += (w << 1) / 3;
67 
68  while (w < width - 5) {
69  READ_PIXELS(u, y, v);
70  READ_PIXELS(y, u, y);
71  READ_PIXELS(v, y, u);
72  READ_PIXELS(y, v, y);
73  w += 6;
74  }
75 
76  if (w++ < width) {
77  READ_PIXELS(u, y, v);
78 
79  if (w++ < width) {
80  val = av_le2ne32(*src++);
81  *y++ = val & 0x3FF;
82 
83  if (w++ < width) {
84  *u++ = (val >> 10) & 0x3FF;
85  *y++ = (val >> 20) & 0x3FF;
86  val = av_le2ne32(*src++);
87  *v++ = val & 0x3FF;
88 
89  if (w++ < width) {
90  *y++ = (val >> 10) & 0x3FF;
91 
92  if (w++ < width) {
93  *u++ = (val >> 20) & 0x3FF;
94  val = av_le2ne32(*src++);
95  *y++ = val & 0x3FF;
96  *v++ = (val >> 10) & 0x3FF;
97 
98  if (w++ < width)
99  *y++ = (val >> 20) & 0x3FF;
100  }
101  }
102  }
103  }
104  }
105 }
106 
107 static int v210_decode_slice(AVCodecContext *avctx, void *arg, int jobnr, int threadnr)
108 {
109  V210DecContext *s = avctx->priv_data;
110  ThreadData *td = arg;
111  AVFrame *frame = td->frame;
112  int stride = td->stride;
113  int slice_start = (avctx->height * jobnr) / s->thread_count;
114  int slice_end = (avctx->height * (jobnr+1)) / s->thread_count;
115  const uint8_t *psrc = td->buf + stride * slice_start;
116  int16_t *py = (uint16_t*)frame->data[0] + slice_start * frame->linesize[0] / 2;
117  int16_t *pu = (uint16_t*)frame->data[1] + slice_start * frame->linesize[1] / 2;
118  int16_t *pv = (uint16_t*)frame->data[2] + slice_start * frame->linesize[2] / 2;
119 
120  for (int h = slice_start; h < slice_end; h++) {
121  decode_row((const uint32_t *)psrc, py, pu, pv, avctx->width, s->unpack_frame);
122  psrc += stride;
123  py += frame->linesize[0] / 2;
124  pu += frame->linesize[1] / 2;
125  pv += frame->linesize[2] / 2;
126  }
127 
128  return 0;
129 }
130 
131 static int v210_stride(int width, int align) {
132  int aligned_width = ((width + align - 1) / align) * align;
133  return aligned_width * 8 / 3;
134 }
135 
136 static int decode_frame(AVCodecContext *avctx, AVFrame *pic,
137  int *got_frame, AVPacket *avpkt)
138 {
139  V210DecContext *s = avctx->priv_data;
140  ThreadData td;
141  int ret, stride, aligned_input;
142  const uint8_t *psrc = avpkt->data;
143 
144  if (s->custom_stride )
145  stride = s->custom_stride > 0 ? s->custom_stride : 0;
146  else {
147  stride = v210_stride(avctx->width, 48);
148  if (avpkt->size < stride * avctx->height) {
149  int align;
150  for (align = 24; align >= 6; align >>= 1) {
151  int small_stride = v210_stride(avctx->width, align);
152  if (avpkt->size == small_stride * avctx->height) {
153  stride = small_stride;
154  if (!s->stride_warning_shown)
155  av_log(avctx, AV_LOG_WARNING, "Broken v210 with too small padding (%d byte) detected\n", align * 8 / 3);
156  s->stride_warning_shown = 1;
157  break;
158  }
159  }
160  if (align < 6 && avctx->codec_tag == MKTAG('b', 'x', 'y', '2'))
161  stride = 0;
162  }
163  }
164 
165  if (stride == 0 && ((avctx->width & 1) || (int64_t)avctx->width * avctx->height > INT_MAX / 6)) {
166  av_log(avctx, AV_LOG_ERROR, "Strideless v210 is not supported for size %dx%d\n", avctx->width, avctx->height);
167  return AVERROR_INVALIDDATA;
168  }
169 
170  if (stride > 0 && avpkt->size < (int64_t)stride * avctx->height ||
171  stride == 0 && avpkt->size < v210_stride(avctx->width * avctx->height, 6)) {
172  av_log(avctx, AV_LOG_ERROR, "packet too small\n");
173  return AVERROR_INVALIDDATA;
174  }
175  if ( avctx->codec_tag == MKTAG('C', '2', '1', '0')
176  && avpkt->size > 64
177  && AV_RN32(psrc) == AV_RN32("INFO")
178  && avpkt->size - 64 >= stride * avctx->height)
179  psrc += 64;
180 
181  aligned_input = !((uintptr_t)psrc & 0x1f) && !(stride & 0x1f);
182  if (aligned_input != s->aligned_input) {
183  s->aligned_input = aligned_input;
185  }
186 
187  if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0)
188  return ret;
189 
190  if (stride) {
191  td.stride = stride;
192  td.buf = psrc;
193  td.frame = pic;
194  avctx->execute2(avctx, v210_decode_slice, &td, NULL, s->thread_count);
195  } else {
196  uint8_t *pointers[4];
197  int linesizes[4];
198  int ret = av_image_alloc(pointers, linesizes, avctx->width, avctx->height, avctx->pix_fmt, 1);
199  if (ret < 0)
200  return ret;
201  decode_row((const uint32_t *)psrc, (uint16_t *)pointers[0], (uint16_t *)pointers[1], (uint16_t *)pointers[2], avctx->width * avctx->height, s->unpack_frame);
202  av_image_copy2(pic->data, pic->linesize, pointers, linesizes,
203  avctx->pix_fmt, avctx->width, avctx->height);
204  av_freep(&pointers[0]);
205  }
206 
207  if (avctx->field_order > AV_FIELD_PROGRESSIVE) {
208  /* we have interlaced material flagged in container */
210  if (avctx->field_order == AV_FIELD_TT || avctx->field_order == AV_FIELD_TB)
212  }
213 
214  *got_frame = 1;
215 
216  return avpkt->size;
217 }
218 
219 #define V210DEC_FLAGS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM
220 static const AVOption v210dec_options[] = {
221  {"custom_stride", "Custom V210 stride", offsetof(V210DecContext, custom_stride), AV_OPT_TYPE_INT,
222  {.i64 = 0}, -1, INT_MAX, V210DEC_FLAGS},
223  {NULL}
224 };
225 
226 static const AVClass v210dec_class = {
227  .class_name = "V210 Decoder",
228  .item_name = av_default_item_name,
229  .option = v210dec_options,
230  .version = LIBAVUTIL_VERSION_INT,
231 };
232 
234  .p.name = "v210",
235  CODEC_LONG_NAME("Uncompressed 4:2:2 10-bit"),
236  .p.type = AVMEDIA_TYPE_VIDEO,
237  .p.id = AV_CODEC_ID_V210,
238  .priv_data_size = sizeof(V210DecContext),
239  .init = decode_init,
241  .p.capabilities = AV_CODEC_CAP_DR1 |
244  .p.priv_class = &v210dec_class,
245 };
v210dec_options
static const AVOption v210dec_options[]
Definition: v210dec.c:220
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
v210_stride
static int v210_stride(int width, int align)
Definition: v210dec.c:131
av_clip
#define av_clip
Definition: common.h:100
u
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:251
AV_FIELD_PROGRESSIVE
@ AV_FIELD_PROGRESSIVE
Definition: defs.h:201
int64_t
long long int64_t
Definition: coverity.c:34
decode_init
static av_cold int decode_init(AVCodecContext *avctx)
Definition: v210dec.c:41
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:374
ThreadData::stride
int stride
Definition: v210dec.c:38
w
uint8_t w
Definition: llviddspenc.c:38
AVPacket::data
uint8_t * data
Definition: packet.h:533
AVCodecContext::field_order
enum AVFieldOrder field_order
Field order.
Definition: avcodec.h:708
READ_PIXELS
#define READ_PIXELS(a, b, c)
Definition: v210dec_init.h:34
AVOption
AVOption.
Definition: opt.h:357
decode_frame
static int decode_frame(AVCodecContext *avctx, AVFrame *pic, int *got_frame, AVPacket *avpkt)
Definition: v210dec.c:136
FFCodec
Definition: codec_internal.h:126
ThreadData::frame
AVFrame * frame
Definition: dsddec.c:72
AVFrame::flags
int flags
Frame flags, a combination of AV_FRAME_FLAGS.
Definition: frame.h:646
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
v210dec_init.h
thread.h
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:395
AV_FRAME_FLAG_TOP_FIELD_FIRST
#define AV_FRAME_FLAG_TOP_FIELD_FIRST
A flag to mark frames where the top field is displayed first if the content is interlaced.
Definition: frame.h:638
AV_FIELD_TT
@ AV_FIELD_TT
Top coded_first, top displayed first.
Definition: defs.h:202
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:130
slice_end
static int slice_end(AVCodecContext *avctx, AVFrame *pict, int *got_output)
Handle slice ends.
Definition: mpeg12dec.c:1719
ThreadData::buf
const uint8_t * buf
Definition: v210dec.c:37
AVCodecContext::thread_count
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition: avcodec.h:1583
unpack_frame
static void unpack_frame(EVRCContext *e)
Frame unpacking for RATE_FULL, RATE_HALF and RATE_QUANT.
Definition: evrcdec.c:110
val
static double val(void *priv, double ch)
Definition: aeval.c:78
AV_FIELD_TB
@ AV_FIELD_TB
Top coded first, bottom displayed first.
Definition: defs.h:204
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
width
#define width
FF_CODEC_DECODE_CB
#define FF_CODEC_DECODE_CB(func)
Definition: codec_internal.h:286
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:198
ff_v210dec_init
static av_unused av_cold void ff_v210dec_init(V210DecContext *s)
Definition: v210dec_init.h:54
ff_thread_get_buffer
int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f, int flags)
Wrapper around get_buffer() for frame-multithreaded codecs.
Definition: pthread_frame.c:986
AVCodecContext::bits_per_raw_sample
int bits_per_raw_sample
Bits per sample/pixel of internal libavcodec pixel/sample format.
Definition: avcodec.h:1575
pointers
Undefined Behavior In the C some operations are like signed integer dereferencing freed pointers
Definition: undefined.txt:4
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:271
V210DecContext
Definition: v210dec.h:26
arg
const char * arg
Definition: jacosubdec.c:67
AV_CODEC_CAP_FRAME_THREADS
#define AV_CODEC_CAP_FRAME_THREADS
Codec supports frame-level multithreading.
Definition: codec.h:110
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
AV_RN32
#define AV_RN32(p)
Definition: intreadwrite.h:358
AV_PIX_FMT_YUV422P10
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:479
av_image_alloc
int av_image_alloc(uint8_t *pointers[4], int linesizes[4], int w, int h, enum AVPixelFormat pix_fmt, int align)
Allocate an image with size w and h and pixel format pix_fmt, and fill pointers and linesizes accordi...
Definition: imgutils.c:218
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:366
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
AVPacket::size
int size
Definition: packet.h:534
codec_internal.h
AV_CODEC_ID_V210
@ AV_CODEC_ID_V210
Definition: codec_id.h:179
align
static const uint8_t *BS_FUNC() align(BSCTX *bc)
Skip bits to a byte boundary.
Definition: bitstream_template.h:411
AV_CODEC_CAP_SLICE_THREADS
#define AV_CODEC_CAP_SLICE_THREADS
Codec supports slice-based (or partition-based) multithreading.
Definition: codec.h:114
ff_v210_decoder
const FFCodec ff_v210_decoder
Definition: v210dec.c:233
v210dec_class
static const AVClass v210dec_class
Definition: v210dec.c:226
internal.h
ThreadData
Used for passing data between threads.
Definition: dsddec.c:71
av_le2ne32
#define av_le2ne32(x)
Definition: bswap.h:92
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:194
AVCodecContext::height
int height
Definition: avcodec.h:618
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:657
AV_FRAME_FLAG_INTERLACED
#define AV_FRAME_FLAG_INTERLACED
A flag to mark frames whose content is interlaced.
Definition: frame.h:633
avcodec.h
stride
#define stride
Definition: h264pred_template.c:537
ret
ret
Definition: filter_design.txt:187
bswap.h
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:71
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
AVCodecContext
main external API structure.
Definition: avcodec.h:445
decode_row
static void decode_row(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, const int width, void(*unpack_frame)(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width))
Definition: v210dec.c:55
V210DEC_FLAGS
#define V210DEC_FLAGS
Definition: v210dec.c:219
av_image_copy2
static void av_image_copy2(uint8_t *const dst_data[4], const int dst_linesizes[4], uint8_t *const src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height)
Wrapper around av_image_copy() to workaround the limitation that the conversion from uint8_t * const ...
Definition: imgutils.h:184
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:245
slice_start
static int slice_start(SliceContext *sc, VVCContext *s, VVCFrameContext *fc, const CodedBitstreamUnit *unit, const int is_first_slice)
Definition: dec.c:704
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
mem.h
AVCodecContext::codec_tag
unsigned int codec_tag
fourcc (LSB first, so "ABCD" -> ('D'<<24) + ('C'<<16) + ('B'<<8) + 'A').
Definition: avcodec.h:470
AVPacket
This structure stores compressed data.
Definition: packet.h:510
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:472
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
v210_decode_slice
static int v210_decode_slice(AVCodecContext *avctx, void *arg, int jobnr, int threadnr)
Definition: v210dec.c:107
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:618
imgutils.h
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:419
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
MKTAG
#define MKTAG(a, b, c, d)
Definition: macros.h:55
h
h
Definition: vp9dsp_template.c:2038
AVCodecContext::execute2
int(* execute2)(struct AVCodecContext *c, int(*func)(struct AVCodecContext *c2, void *arg, int jobnr, int threadnr), void *arg2, int *ret, int count)
The codec may call this to execute several independent things.
Definition: avcodec.h:1632
v210dec.h