2 * Copyright (c) 2012 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)
29 #include "libavutil/avassert.h"
34 #include "libutvideo.h"
37 static av_cold
int utvideo_encode_init(AVCodecContext
*avctx
)
39 UtVideoContext
*utv
= (UtVideoContext
*)avctx
->priv_data
;
41 uint32_t flags
, in_format
;
43 switch (avctx
->pix_fmt
) {
44 case AV_PIX_FMT_YUV420P
:
45 in_format
= UTVF_YV12
;
46 avctx
->bits_per_coded_sample
= 12;
47 if (avctx
->colorspace
== AVCOL_SPC_BT709
)
48 avctx
->codec_tag
= MKTAG('U', 'L', 'H', '0');
50 avctx
->codec_tag
= MKTAG('U', 'L', 'Y', '0');
52 case AV_PIX_FMT_YUYV422
:
53 in_format
= UTVF_YUYV
;
54 avctx
->bits_per_coded_sample
= 16;
55 if (avctx
->colorspace
== AVCOL_SPC_BT709
)
56 avctx
->codec_tag
= MKTAG('U', 'L', 'H', '2');
58 avctx
->codec_tag
= MKTAG('U', 'L', 'Y', '2');
60 case AV_PIX_FMT_BGR24
:
61 in_format
= UTVF_NFCC_BGR_BU
;
62 avctx
->bits_per_coded_sample
= 24;
63 avctx
->codec_tag
= MKTAG('U', 'L', 'R', 'G');
65 case AV_PIX_FMT_RGB32
:
66 in_format
= UTVF_NFCC_BGRA_BU
;
67 avctx
->bits_per_coded_sample
= 32;
68 avctx
->codec_tag
= MKTAG('U', 'L', 'R', 'A');
71 return AVERROR(EINVAL
);
74 /* Check before we alloc anything */
75 if (avctx
->prediction_method
!= 0 && avctx
->prediction_method
!= 2) {
76 av_log(avctx
, AV_LOG_ERROR
, "Invalid prediction method.\n");
77 return AVERROR(EINVAL
);
80 flags
= ((avctx
->prediction_method
+ 1) << 8) | (avctx
->thread_count
- 1);
82 avctx
->priv_data
= utv
;
83 avctx
->coded_frame
= av_frame_alloc();
85 /* Alloc extradata buffer */
86 info
= (UtVideoExtra
*)av_malloc(sizeof(*info
));
89 av_log(avctx
, AV_LOG_ERROR
, "Could not allocate extradata buffer.\n");
90 return AVERROR(ENOMEM
);
94 * We use this buffer to hold the data that Ut Video returns,
95 * since we cannot decode planes separately with it.
97 utv
->buf_size
= avpicture_get_size(avctx
->pix_fmt
,
98 avctx
->width
, avctx
->height
);
99 utv
->buffer
= (uint8_t *)av_malloc(utv
->buf_size
);
101 if (utv
->buffer
== NULL
) {
102 av_log(avctx
, AV_LOG_ERROR
, "Could not allocate output buffer.\n");
103 return AVERROR(ENOMEM
);
107 * Create a Ut Video instance. Since the function wants
108 * an "interface name" string, pass it the name of the lib.
110 utv
->codec
= CCodec::CreateInstance(UNFCC(avctx
->codec_tag
), "libavcodec");
112 /* Initialize encoder */
113 utv
->codec
->EncodeBegin(in_format
, avctx
->width
, avctx
->height
,
114 CBGROSSWIDTH_WINDOWS
);
116 /* Get extradata from encoder */
117 avctx
->extradata_size
= utv
->codec
->EncodeGetExtraDataSize();
118 utv
->codec
->EncodeGetExtraData(info
, avctx
->extradata_size
, in_format
,
119 avctx
->width
, avctx
->height
,
120 CBGROSSWIDTH_WINDOWS
);
121 avctx
->extradata
= (uint8_t *)info
;
124 utv
->codec
->SetState(&flags
, sizeof(flags
));
129 static int utvideo_encode_frame(AVCodecContext
*avctx
, AVPacket
*pkt
,
130 const AVFrame
*pic
, int *got_packet
)
132 UtVideoContext
*utv
= (UtVideoContext
*)avctx
->priv_data
;
133 int w
= avctx
->width
, h
= avctx
->height
;
134 int ret
, rgb_size
, i
;
140 if ((ret
= ff_alloc_packet2(avctx
, pkt
, utv
->buf_size
)) < 0)
145 /* Move input if needed data into Ut Video friendly buffer */
146 switch (avctx
->pix_fmt
) {
147 case AV_PIX_FMT_YUV420P
:
151 for (i
= 0; i
< h
; i
++) {
152 memcpy(y
, pic
->data
[0] + i
* pic
->linesize
[0], w
);
155 for (i
= 0; i
< h
/ 2; i
++) {
156 memcpy(u
, pic
->data
[2] + i
* pic
->linesize
[2], w
>> 1);
157 memcpy(v
, pic
->data
[1] + i
* pic
->linesize
[1], w
>> 1);
162 case AV_PIX_FMT_YUYV422
:
163 for (i
= 0; i
< h
; i
++)
164 memcpy(utv
->buffer
+ i
* (w
<< 1),
165 pic
->data
[0] + i
* pic
->linesize
[0], w
<< 1);
167 case AV_PIX_FMT_BGR24
:
168 case AV_PIX_FMT_RGB32
:
169 /* Ut Video takes bottom-up BGR */
170 rgb_size
= avctx
->pix_fmt
== AV_PIX_FMT_BGR24
? 3 : 4;
171 for (i
= 0; i
< h
; i
++)
172 memcpy(utv
->buffer
+ (h
- i
- 1) * w
* rgb_size
,
173 pic
->data
[0] + i
* pic
->linesize
[0],
177 return AVERROR(EINVAL
);
181 pkt
->size
= utv
->codec
->EncodeFrame(dst
, &keyframe
, utv
->buffer
);
184 av_log(avctx
, AV_LOG_ERROR
, "EncodeFrame failed!\n");
185 return AVERROR_INVALIDDATA
;
189 * Ut Video is intra-only and every frame is a keyframe,
190 * and the API always returns true. In case something
191 * durastic changes in the future, such as inter support,
192 * assert that this is true.
194 av_assert2(keyframe
== true);
195 avctx
->coded_frame
->key_frame
= 1;
196 avctx
->coded_frame
->pict_type
= AV_PICTURE_TYPE_I
;
198 pkt
->flags
|= AV_PKT_FLAG_KEY
;
203 static av_cold
int utvideo_encode_close(AVCodecContext
*avctx
)
205 UtVideoContext
*utv
= (UtVideoContext
*)avctx
->priv_data
;
207 av_freep(&avctx
->coded_frame
);
208 av_freep(&avctx
->extradata
);
209 av_freep(&utv
->buffer
);
211 utv
->codec
->EncodeEnd();
212 CCodec::DeleteInstance(utv
->codec
);
217 AVCodec ff_libutvideo_encoder
= {
219 NULL_IF_CONFIG_SMALL("Ut Video"),
222 CODEC_CAP_AUTO_THREADS
| CODEC_CAP_LOSSLESS
,
223 NULL
, /* supported_framerates */
224 (const enum AVPixelFormat
[]) {
225 AV_PIX_FMT_YUV420P
, AV_PIX_FMT_YUYV422
, AV_PIX_FMT_BGR24
,
226 AV_PIX_FMT_RGB32
, AV_PIX_FMT_NONE
228 NULL
, /* supported_samplerates */
229 NULL
, /* sample_fmts */
230 NULL
, /* channel_layouts */
232 NULL
, /* priv_class */
234 sizeof(UtVideoContext
),
236 NULL
, /* init_thread_copy */
237 NULL
, /* update_thread_context */
239 NULL
, /* init_static_data */
242 utvideo_encode_frame
,
244 utvideo_encode_close
,