FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
libutvideoenc.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012 Derek Buitenhuis
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 General Public
8  * License as published by the Free Software Foundation;
9  * version 2 of the License.
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  * General Public License for more details.
15  *
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
19  */
20 
21 /**
22  * @file
23  * Known FOURCCs:
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)
26  */
27 
28 extern "C" {
29 #include "libavutil/avassert.h"
30 #include "avcodec.h"
31 #include "internal.h"
32 }
33 
34 #include "libutvideo.h"
35 #include "put_bits.h"
36 
38 {
39  UtVideoContext *utv = (UtVideoContext *)avctx->priv_data;
40  UtVideoExtra *info;
41  uint32_t flags, in_format;
42  int ret;
43 
44  switch (avctx->pix_fmt) {
45  case AV_PIX_FMT_YUV420P:
46  in_format = UTVF_YV12;
47  avctx->bits_per_coded_sample = 12;
48  if (avctx->colorspace == AVCOL_SPC_BT709)
49  avctx->codec_tag = MKTAG('U', 'L', 'H', '0');
50  else
51  avctx->codec_tag = MKTAG('U', 'L', 'Y', '0');
52  break;
53  case AV_PIX_FMT_YUYV422:
54  in_format = UTVF_YUYV;
55  avctx->bits_per_coded_sample = 16;
56  if (avctx->colorspace == AVCOL_SPC_BT709)
57  avctx->codec_tag = MKTAG('U', 'L', 'H', '2');
58  else
59  avctx->codec_tag = MKTAG('U', 'L', 'Y', '2');
60  break;
61  case AV_PIX_FMT_BGR24:
62  in_format = UTVF_NFCC_BGR_BU;
63  avctx->bits_per_coded_sample = 24;
64  avctx->codec_tag = MKTAG('U', 'L', 'R', 'G');
65  break;
66  case AV_PIX_FMT_RGB32:
67  in_format = UTVF_NFCC_BGRA_BU;
68  avctx->bits_per_coded_sample = 32;
69  avctx->codec_tag = MKTAG('U', 'L', 'R', 'A');
70  break;
71  default:
72  return AVERROR(EINVAL);
73  }
74 
75  /* Check before we alloc anything */
76  if (avctx->prediction_method != 0 && avctx->prediction_method != 2) {
77  av_log(avctx, AV_LOG_ERROR, "Invalid prediction method.\n");
78  return AVERROR(EINVAL);
79  }
80 
81  flags = ((avctx->prediction_method + 1) << 8) | (avctx->thread_count - 1);
82 
83  avctx->priv_data = utv;
84  avctx->coded_frame = av_frame_alloc();
85 
86  /* Alloc extradata buffer */
87  info = (UtVideoExtra *)av_malloc(sizeof(*info));
88 
89  if (!info) {
90  av_log(avctx, AV_LOG_ERROR, "Could not allocate extradata buffer.\n");
91  return AVERROR(ENOMEM);
92  }
93 
94  /*
95  * We use this buffer to hold the data that Ut Video returns,
96  * since we cannot decode planes separately with it.
97  */
98  ret = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height);
99  if (ret < 0)
100  return ret;
101  utv->buf_size = ret;
102 
103  utv->buffer = (uint8_t *)av_malloc(utv->buf_size);
104 
105  if (utv->buffer == NULL) {
106  av_log(avctx, AV_LOG_ERROR, "Could not allocate output buffer.\n");
107  av_free(info);
108  return AVERROR(ENOMEM);
109  }
110 
111  /*
112  * Create a Ut Video instance. Since the function wants
113  * an "interface name" string, pass it the name of the lib.
114  */
115  utv->codec = CCodec::CreateInstance(UNFCC(avctx->codec_tag), "libavcodec");
116 
117  /* Initialize encoder */
118  utv->codec->EncodeBegin(in_format, avctx->width, avctx->height,
119  CBGROSSWIDTH_WINDOWS);
120 
121  /* Get extradata from encoder */
122  avctx->extradata_size = utv->codec->EncodeGetExtraDataSize();
123  utv->codec->EncodeGetExtraData(info, avctx->extradata_size, in_format,
124  avctx->width, avctx->height,
125  CBGROSSWIDTH_WINDOWS);
126  avctx->extradata = (uint8_t *)info;
127 
128  /* Set flags */
129  utv->codec->SetState(&flags, sizeof(flags));
130 
131  return 0;
132 }
133 
135  const AVFrame *pic, int *got_packet)
136 {
137  UtVideoContext *utv = (UtVideoContext *)avctx->priv_data;
138  int w = avctx->width, h = avctx->height;
139  int ret, rgb_size, i;
140  bool keyframe;
141  uint8_t *y, *u, *v;
142  uint8_t *dst;
143 
144  /* Alloc buffer */
145  if ((ret = ff_alloc_packet2(avctx, pkt, utv->buf_size)) < 0)
146  return ret;
147 
148  dst = pkt->data;
149 
150  /* Move input if needed data into Ut Video friendly buffer */
151  switch (avctx->pix_fmt) {
152  case AV_PIX_FMT_YUV420P:
153  y = utv->buffer;
154  u = y + w * h;
155  v = u + w * h / 4;
156  for (i = 0; i < h; i++) {
157  memcpy(y, pic->data[0] + i * pic->linesize[0], w);
158  y += w;
159  }
160  for (i = 0; i < h / 2; i++) {
161  memcpy(u, pic->data[2] + i * pic->linesize[2], w >> 1);
162  memcpy(v, pic->data[1] + i * pic->linesize[1], w >> 1);
163  u += w >> 1;
164  v += w >> 1;
165  }
166  break;
167  case AV_PIX_FMT_YUYV422:
168  for (i = 0; i < h; i++)
169  memcpy(utv->buffer + i * (w << 1),
170  pic->data[0] + i * pic->linesize[0], w << 1);
171  break;
172  case AV_PIX_FMT_BGR24:
173  case AV_PIX_FMT_RGB32:
174  /* Ut Video takes bottom-up BGR */
175  rgb_size = avctx->pix_fmt == AV_PIX_FMT_BGR24 ? 3 : 4;
176  for (i = 0; i < h; i++)
177  memcpy(utv->buffer + (h - i - 1) * w * rgb_size,
178  pic->data[0] + i * pic->linesize[0],
179  w * rgb_size);
180  break;
181  default:
182  return AVERROR(EINVAL);
183  }
184 
185  /* Encode frame */
186  pkt->size = utv->codec->EncodeFrame(dst, &keyframe, utv->buffer);
187 
188  if (!pkt->size) {
189  av_log(avctx, AV_LOG_ERROR, "EncodeFrame failed!\n");
190  return AVERROR_INVALIDDATA;
191  }
192 
193  /*
194  * Ut Video is intra-only and every frame is a keyframe,
195  * and the API always returns true. In case something
196  * durastic changes in the future, such as inter support,
197  * assert that this is true.
198  */
199  av_assert2(keyframe == true);
200  avctx->coded_frame->key_frame = 1;
202 
203  pkt->flags |= AV_PKT_FLAG_KEY;
204  *got_packet = 1;
205  return 0;
206 }
207 
209 {
210  UtVideoContext *utv = (UtVideoContext *)avctx->priv_data;
211 
212  av_frame_free(&avctx->coded_frame);
213  av_freep(&avctx->extradata);
214  av_freep(&utv->buffer);
215 
216  utv->codec->EncodeEnd();
217  CCodec::DeleteInstance(utv->codec);
218 
219  return 0;
220 }
221 
223  "libutvideo",
224  NULL_IF_CONFIG_SMALL("Ut Video"),
228  NULL, /* supported_framerates */
229  (const enum AVPixelFormat[]) {
232  },
233  NULL, /* supported_samplerates */
234  NULL, /* sample_fmts */
235  NULL, /* channel_layouts */
236  0, /* max_lowres */
237  NULL, /* priv_class */
238  NULL, /* profiles */
239  sizeof(UtVideoContext),
240  NULL, /* next */
241  NULL, /* init_thread_copy */
242  NULL, /* update_thread_context */
243  NULL, /* defaults */
244  NULL, /* init_static_data */
246  NULL, /* encode */
248  NULL, /* decode */
250  NULL, /* flush */
251 };