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 "internal.h"
26 #include "v210dec.h"
27 #include "libavutil/bswap.h"
28 #include "libavutil/internal.h"
29 #include "libavutil/mem.h"
30 #include "libavutil/intreadwrite.h"
31 #include "thread.h"
32 
33 #define READ_PIXELS(a, b, c) \
34  do { \
35  val = av_le2ne32(*src++); \
36  *a++ = val & 0x3FF; \
37  *b++ = (val >> 10) & 0x3FF; \
38  *c++ = (val >> 20) & 0x3FF; \
39  } while (0)
40 
41 typedef struct ThreadData {
42  AVFrame *frame;
44  int stride;
45 } ThreadData;
46 
47 static void v210_planar_unpack_c(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width)
48 {
49  uint32_t val;
50  int i;
51 
52  for( i = 0; i < width-5; i += 6 ){
53  READ_PIXELS(u, y, v);
54  READ_PIXELS(y, u, y);
55  READ_PIXELS(v, y, u);
56  READ_PIXELS(y, v, y);
57  }
58 }
59 
61 {
63  if (ARCH_X86)
65 }
66 
68 {
69  V210DecContext *s = avctx->priv_data;
70 
72  avctx->bits_per_raw_sample = 10;
73 
74  s->thread_count = av_clip(avctx->thread_count, 1, avctx->height/4);
75  s->aligned_input = 0;
76  ff_v210dec_init(s);
77 
78  return 0;
79 }
80 
81 static int v210_decode_slice(AVCodecContext *avctx, void *arg, int jobnr, int threadnr)
82 {
83  V210DecContext *s = avctx->priv_data;
84  int h, w;
85  ThreadData *td = arg;
86  AVFrame *frame = td->frame;
87  int stride = td->stride;
88  int slice_start = (avctx->height * jobnr) / s->thread_count;
89  int slice_end = (avctx->height * (jobnr+1)) / s->thread_count;
90  uint8_t *psrc = td->buf + stride * slice_start;
91  uint16_t *y, *u, *v;
92 
93  y = (uint16_t*)frame->data[0] + slice_start * frame->linesize[0] / 2;
94  u = (uint16_t*)frame->data[1] + slice_start * frame->linesize[1] / 2;
95  v = (uint16_t*)frame->data[2] + slice_start * frame->linesize[2] / 2;
96  for (h = slice_start; h < slice_end; h++) {
97  const uint32_t *src = (const uint32_t*)psrc;
98  uint32_t val;
99 
100  w = (avctx->width / 12) * 12;
101  s->unpack_frame(src, y, u, v, w);
102 
103  y += w;
104  u += w >> 1;
105  v += w >> 1;
106  src += (w << 1) / 3;
107 
108  if (w < avctx->width - 5) {
109  READ_PIXELS(u, y, v);
110  READ_PIXELS(y, u, y);
111  READ_PIXELS(v, y, u);
112  READ_PIXELS(y, v, y);
113  w += 6;
114  }
115 
116  if (w < avctx->width - 1) {
117  READ_PIXELS(u, y, v);
118 
119  val = av_le2ne32(*src++);
120  *y++ = val & 0x3FF;
121  if (w < avctx->width - 3) {
122  *u++ = (val >> 10) & 0x3FF;
123  *y++ = (val >> 20) & 0x3FF;
124 
125  val = av_le2ne32(*src++);
126  *v++ = val & 0x3FF;
127  *y++ = (val >> 10) & 0x3FF;
128  }
129  }
130 
131  psrc += stride;
132  y += frame->linesize[0] / 2 - avctx->width + (avctx->width & 1);
133  u += frame->linesize[1] / 2 - avctx->width / 2;
134  v += frame->linesize[2] / 2 - avctx->width / 2;
135  }
136 
137  return 0;
138 }
139 
140 static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
141  AVPacket *avpkt)
142 {
143  V210DecContext *s = avctx->priv_data;
144  ThreadData td;
145  int ret, stride, aligned_input;
146  ThreadFrame frame = { .f = data };
147  AVFrame *pic = data;
148  const uint8_t *psrc = avpkt->data;
149 
150  if (s->custom_stride )
151  stride = s->custom_stride;
152  else {
153  int aligned_width = ((avctx->width + 47) / 48) * 48;
154  stride = aligned_width * 8 / 3;
155  }
156 
157  if (avpkt->size < stride * avctx->height) {
158  if ((((avctx->width + 23) / 24) * 24 * 8) / 3 * avctx->height == avpkt->size) {
159  stride = avpkt->size / avctx->height;
160  if (!s->stride_warning_shown)
161  av_log(avctx, AV_LOG_WARNING, "Broken v210 with too small padding (64 byte) detected\n");
162  s->stride_warning_shown = 1;
163  } else {
164  av_log(avctx, AV_LOG_ERROR, "packet too small\n");
165  return AVERROR_INVALIDDATA;
166  }
167  }
168  td.stride = stride;
169  if ( avctx->codec_tag == MKTAG('C', '2', '1', '0')
170  && avpkt->size > 64
171  && AV_RN32(psrc) == AV_RN32("INFO")
172  && avpkt->size - 64 >= stride * avctx->height)
173  psrc += 64;
174 
175  aligned_input = !((uintptr_t)psrc & 0x1f) && !(stride & 0x1f);
176  if (aligned_input != s->aligned_input) {
177  s->aligned_input = aligned_input;
178  ff_v210dec_init(s);
179  }
180 
181  if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
182  return ret;
183 
185  pic->key_frame = 1;
186 
187  td.buf = (uint8_t*)psrc;
188  td.frame = pic;
189  avctx->execute2(avctx, v210_decode_slice, &td, NULL, s->thread_count);
190 
191  if (avctx->field_order > AV_FIELD_PROGRESSIVE) {
192  /* we have interlaced material flagged in container */
193  pic->interlaced_frame = 1;
194  if (avctx->field_order == AV_FIELD_TT || avctx->field_order == AV_FIELD_TB)
195  pic->top_field_first = 1;
196  }
197 
198  *got_frame = 1;
199 
200  return avpkt->size;
201 }
202 
203 #define V210DEC_FLAGS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM
204 static const AVOption v210dec_options[] = {
205  {"custom_stride", "Custom V210 stride", offsetof(V210DecContext, custom_stride), AV_OPT_TYPE_INT,
206  {.i64 = 0}, INT_MIN, INT_MAX, V210DEC_FLAGS},
207  {NULL}
208 };
209 
210 static const AVClass v210dec_class = {
211  .class_name = "V210 Decoder",
212  .item_name = av_default_item_name,
213  .option = v210dec_options,
214  .version = LIBAVUTIL_VERSION_INT,
215 };
216 
218  .name = "v210",
219  .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"),
220  .type = AVMEDIA_TYPE_VIDEO,
221  .id = AV_CODEC_ID_V210,
222  .priv_data_size = sizeof(V210DecContext),
223  .init = decode_init,
224  .decode = decode_frame,
225  .capabilities = AV_CODEC_CAP_DR1 |
228  .priv_class = &v210dec_class,
229 };
int stride_warning_shown
Definition: v210dec.h:31
#define NULL
Definition: coverity.c:32
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static av_cold int decode_init(AVCodecContext *avctx)
Definition: v210dec.c:67
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
AVOption.
Definition: opt.h:246
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
av_cold void ff_v210dec_init(V210DecContext *s)
Definition: v210dec.c:60
#define READ_PIXELS(a, b, c)
Definition: v210dec.c:33
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
AVFrame * frame
Definition: dsddec.c:65
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
Memory handling functions.
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int size
Definition: avcodec.h:1534
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1831
int bits_per_raw_sample
Bits per sample/pixel of internal libavcodec pixel/sample format.
Definition: avcodec.h:2852
#define av_le2ne32(x)
Definition: bswap.h:96
AVCodec.
Definition: avcodec.h:3555
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:71
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:72
uint8_t
#define av_cold
Definition: attributes.h:82
Multithreading support functions.
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:252
uint8_t * data
Definition: avcodec.h:1533
int interlaced_frame
The content of the picture is interlaced.
Definition: frame.h:442
#define av_log(a,...)
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#define td
Definition: regdef.h:70
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
const uint8_t * src
Definition: vf_bm3d.c:56
const char * arg
Definition: jacosubdec.c:66
const char * name
Name of the codec implementation.
Definition: avcodec.h:3562
#define AV_CODEC_CAP_FRAME_THREADS
Codec supports frame-level multithreading.
Definition: avcodec.h:1055
common internal API header
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:378
int width
picture width / height.
Definition: avcodec.h:1794
void(* unpack_frame)(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width)
Definition: v210dec.h:32
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: v210dec.c:140
static const AVClass v210dec_class
Definition: v210dec.c:210
double * data[MAX_DATA][NUM_PLANES]
int thread_count
thread count is used to decide how many independent tasks should be passed to execute() ...
Definition: avcodec.h:2880
int thread_count
Definition: v210dec.h:30
#define AV_CODEC_CAP_SLICE_THREADS
Codec supports slice-based (or partition-based) multithreading.
Definition: avcodec.h:1059
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:2940
Libavcodec external API header.
Used for passing data between threads.
Definition: dsddec.c:64
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:326
int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags)
Wrapper around get_buffer() for frame-multithreaded codecs.
AVCodec ff_v210_decoder
Definition: v210dec.c:217
main external API structure.
Definition: avcodec.h:1621
unsigned int codec_tag
fourcc (LSB first, so "ABCD" -> (&#39;D&#39;<<24) + (&#39;C&#39;<<16) + (&#39;B&#39;<<8) + &#39;A&#39;).
Definition: avcodec.h:1646
int aligned_input
Definition: v210dec.h:29
Describe the class of an AVClass context structure.
Definition: log.h:67
int custom_stride
Definition: v210dec.h:28
AVPacket * avpkt
Definition: dsddec.c:66
byte swapping routines
void ff_v210_x86_init(V210DecContext *s)
Definition: v210-init.c:30
uint8_t * buf
Definition: v210dec.c:43
#define AV_RN32(p)
Definition: intreadwrite.h:364
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:398
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:309
GLint GLenum GLboolean GLsizei stride
Definition: opengl_enc.c:104
common internal api header.
static int v210_decode_slice(AVCodecContext *avctx, void *arg, int jobnr, int threadnr)
Definition: v210dec.c:81
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2043
void * priv_data
Definition: avcodec.h:1648
#define V210DEC_FLAGS
Definition: v210dec.c:203
int top_field_first
If the content is interlaced, is top field displayed first.
Definition: frame.h:447
static void v210_planar_unpack_c(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width)
Definition: v210dec.c:47
int key_frame
1 -> keyframe, 0-> not
Definition: frame.h:373
const void ** s
enum AVFieldOrder field_order
Field order.
Definition: avcodec.h:2278
#define MKTAG(a, b, c, d)
Definition: common.h:366
static double val(void *priv, double ch)
Definition: aeval.c:76
This structure stores compressed data.
Definition: avcodec.h:1510
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
Definition: avcodec.h:999
int stride
Definition: v210dec.c:44
static const AVOption v210dec_options[]
Definition: v210dec.c:204