2 * Copyright (c) 2011 Derek Buitenhuis
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public
8 * License as published by the Free Software Foundation;
9 * version 2 of the License.
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 * General Public License for more details.
16 * You should have received a copy of the GNU 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
24 * 'ULY0' (YCbCr 4:2:0), 'ULY2' (YCbCr 4:2:2), 'ULRG' (RGB), 'ULRA' (RGBA),
25 * 'ULH0' (YCbCr 4:2:0 BT.709), 'ULH2' (YCbCr 4:2:2 BT.709)
32 #include "libutvideo.h"
35 static av_cold
int utvideo_decode_init(AVCodecContext
*avctx
)
37 UtVideoContext
*utv
= (UtVideoContext
*)avctx
->priv_data
;
42 if (avctx
->extradata_size
!= 16 && avctx
->extradata_size
!= 8 ) {
43 av_log(avctx
, AV_LOG_ERROR
, "Extradata size (%d) mismatch.\n", avctx
->extradata_size
);
48 info
.version
= AV_RL32(avctx
->extradata
);
49 info
.original_format
= AV_RL32(avctx
->extradata
+ 4);
50 info
.frameinfo_size
= AV_RL32(avctx
->extradata
+ 8);
51 info
.flags
= AV_RL32(avctx
->extradata
+ 12);
53 /* Pick format based on FOURCC */
54 switch (avctx
->codec_tag
) {
56 case MKTAG('U', 'L', 'H', '0'):
57 avctx
->pix_fmt
= AV_PIX_FMT_YUV420P
;
58 avctx
->colorspace
= AVCOL_SPC_BT709
;
61 case MKTAG('U', 'L', 'H', '2'):
62 avctx
->pix_fmt
= AV_PIX_FMT_YUYV422
;
63 avctx
->colorspace
= AVCOL_SPC_BT709
;
67 case MKTAG('U', 'L', 'Y', '0'):
68 avctx
->pix_fmt
= AV_PIX_FMT_YUV420P
;
71 case MKTAG('U', 'L', 'Y', '2'):
72 avctx
->pix_fmt
= AV_PIX_FMT_YUYV422
;
75 case MKTAG('U', 'L', 'R', 'G'):
76 avctx
->pix_fmt
= AV_PIX_FMT_BGR24
;
77 format
= UTVF_NFCC_BGR_BU
;
79 case MKTAG('U', 'L', 'R', 'A'):
80 avctx
->pix_fmt
= AV_PIX_FMT_RGB32
;
81 format
= UTVF_NFCC_BGRA_BU
;
84 case MKTAG('U', 'Q', 'Y', '2'):
85 avctx
->pix_fmt
= AV_PIX_FMT_YUV422P10
;
90 av_log(avctx
, AV_LOG_ERROR
,
91 "Not a Ut Video FOURCC: %X\n", avctx
->codec_tag
);
95 /* Only allocate the buffer once */
96 utv
->buf_size
= avpicture_get_size(avctx
->pix_fmt
, avctx
->width
, avctx
->height
);
98 if (format
== UTVF_v210
)
99 utv
->buf_size
+= avctx
->height
* ((avctx
->width
+ 47) / 48) * 128; // the linesize used by the decoder, this does not seem to be exported
101 utv
->buffer
= (uint8_t *)av_malloc(utv
->buf_size
* sizeof(uint8_t));
103 if (utv
->buffer
== NULL
) {
104 av_log(avctx
, AV_LOG_ERROR
, "Unable to allocate output buffer.\n");
108 /* Allocate the output frame */
109 avctx
->coded_frame
= av_frame_alloc();
111 /* Ut Video only supports 8-bit */
112 avctx
->bits_per_raw_sample
= 8;
114 /* Is it interlaced? */
115 avctx
->coded_frame
->interlaced_frame
= info
.flags
& 0x800 ? 1 : 0;
117 /* Apparently Ut Video doesn't store this info... */
118 avctx
->coded_frame
->top_field_first
= 1;
121 * Create a Ut Video instance. Since the function wants
122 * an "interface name" string, pass it the name of the lib.
124 utv
->codec
= CCodec::CreateInstance(UNFCC(avctx
->codec_tag
), "libavcodec");
126 /* Initialize Decoding */
127 begin_ret
= utv
->codec
->DecodeBegin(format
, avctx
->width
, avctx
->height
,
128 CBGROSSWIDTH_WINDOWS
, &info
, sizeof(UtVideoExtra
));
130 /* Check to see if the decoder initlized properly */
131 if (begin_ret
!= 0) {
132 av_log(avctx
, AV_LOG_ERROR
,
133 "Could not initialize decoder: %d\n", begin_ret
);
140 static int utvideo_decode_frame(AVCodecContext
*avctx
, void *data
,
141 int *got_frame
, AVPacket
*avpkt
)
143 UtVideoContext
*utv
= (UtVideoContext
*)avctx
->priv_data
;
144 AVFrame
*pic
= avctx
->coded_frame
;
145 int w
= avctx
->width
, h
= avctx
->height
;
149 pic
->pict_type
= AV_PICTURE_TYPE_I
;
152 /* Decode the frame */
153 utv
->codec
->DecodeFrame(utv
->buffer
, avpkt
->data
, true);
155 /* Set the output data depending on the colorspace */
156 switch (avctx
->pix_fmt
) {
157 case AV_PIX_FMT_YUV420P
:
158 pic
->linesize
[0] = w
;
159 pic
->linesize
[1] = pic
->linesize
[2] = w
/ 2;
160 pic
->data
[0] = utv
->buffer
;
161 pic
->data
[2] = utv
->buffer
+ (w
* h
);
162 pic
->data
[1] = pic
->data
[2] + (w
* h
/ 4);
164 case AV_PIX_FMT_YUYV422
:
165 pic
->linesize
[0] = w
* 2;
166 pic
->data
[0] = utv
->buffer
;
168 case AV_PIX_FMT_YUV422P10
: {
171 int linesize
= ((w
+ 47) / 48) * 128;
173 pic
->linesize
[0] = w
* 2;
175 pic
->linesize
[2] = w
;
176 pic
->data
[0] = utv
->buffer
+ linesize
* h
;
177 pic
->data
[1] = pic
->data
[0] + h
*pic
->linesize
[0];
178 pic
->data
[2] = pic
->data
[1] + h
*pic
->linesize
[1];
179 y
= (uint16_t*)pic
->data
[0];
180 u
= (uint16_t*)pic
->data
[1];
181 v
= (uint16_t*)pic
->data
[2];
182 for (j
= 0; j
< h
; j
++) {
183 const uint8_t *in
= utv
->buffer
+ j
* linesize
;
185 for (i
= 0; i
+ 1 < w
; i
+= 6, in
+= 4) {
191 *y
++ = (a
>>10) & 0x3FF;
192 *v
++ = (a
>>20) & 0x3FF;
200 *u
++ = (b
>>10) & 0x3FF;
201 *y
++ = (b
>>20) & 0x3FF;
203 *y
++ = (a
>>10) & 0x3FF;
210 *u
++ = (a
>>20) & 0x3FF;
212 *v
++ = (b
>>10) & 0x3FF;
213 *y
++ = (b
>>20) & 0x3FF;
218 case AV_PIX_FMT_BGR24
:
219 case AV_PIX_FMT_RGB32
:
220 /* Make the linesize negative, since Ut Video uses bottom-up BGR */
221 pic
->linesize
[0] = -1 * w
* (avctx
->pix_fmt
== AV_PIX_FMT_BGR24
? 3 : 4);
222 pic
->data
[0] = utv
->buffer
+ utv
->buf_size
+ pic
->linesize
[0];
227 av_frame_move_ref((AVFrame
*)data
, pic
);
232 static av_cold
int utvideo_decode_close(AVCodecContext
*avctx
)
234 UtVideoContext
*utv
= (UtVideoContext
*)avctx
->priv_data
;
237 av_frame_free(&avctx
->coded_frame
);
238 av_freep(&utv
->buffer
);
240 /* Finish decoding and clean up the instance */
241 utv
->codec
->DecodeEnd();
242 CCodec::DeleteInstance(utv
->codec
);
247 AVCodec ff_libutvideo_decoder
= {
249 NULL_IF_CONFIG_SMALL("Ut Video"),
253 NULL
, //supported_framerates
255 NULL
, //supported_samplerates
257 NULL
, //channel_layouts
261 sizeof(UtVideoContext
),
263 NULL
, //init_thread_copy
264 NULL
, //update_thread_context
266 NULL
, //init_static_data
270 utvideo_decode_frame
,
271 utvideo_decode_close
,