blob: cf4baa1d827fdc734f5b8b6de4a1d06676f2914c
1 | /* |
2 | * Dirac encoder support via Schroedinger libraries |
3 | * Copyright (c) 2008 BBC, Anuradha Suraparaju <asuraparaju at gmail dot com > |
4 | * |
5 | * This file is part of FFmpeg. |
6 | * |
7 | * FFmpeg is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 of the License, or (at your option) any later version. |
11 | * |
12 | * FFmpeg is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with FFmpeg; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ |
21 | |
22 | /** |
23 | * @file |
24 | * Dirac encoder support via libschroedinger-1.0 libraries. More details about |
25 | * the Schroedinger project can be found at http://www.diracvideo.org/. |
26 | * The library implements Dirac Specification Version 2.2 |
27 | * (http://dirac.sourceforge.net/specification.html). |
28 | */ |
29 | |
30 | #include <schroedinger/schro.h> |
31 | #include <schroedinger/schrodebug.h> |
32 | #include <schroedinger/schrovideoformat.h> |
33 | |
34 | #include "libavutil/attributes.h" |
35 | #include "libavutil/avassert.h" |
36 | #include "libavutil/imgutils.h" |
37 | #include "libavutil/opt.h" |
38 | |
39 | #include "avcodec.h" |
40 | #include "internal.h" |
41 | #include "libschroedinger.h" |
42 | #include "bytestream.h" |
43 | |
44 | |
45 | /** libschroedinger encoder private data */ |
46 | typedef struct SchroEncoderParams { |
47 | AVClass *class; |
48 | |
49 | /** Schroedinger video format */ |
50 | SchroVideoFormat *format; |
51 | |
52 | /** Schroedinger frame format */ |
53 | SchroFrameFormat frame_format; |
54 | |
55 | /** frame size */ |
56 | int frame_size; |
57 | |
58 | /** Schroedinger encoder handle*/ |
59 | SchroEncoder* encoder; |
60 | |
61 | /** buffer to store encoder output before writing it to the frame queue*/ |
62 | unsigned char *enc_buf; |
63 | |
64 | /** Size of encoder buffer*/ |
65 | int enc_buf_size; |
66 | |
67 | /** queue storing encoded frames */ |
68 | FFSchroQueue enc_frame_queue; |
69 | |
70 | /** end of sequence signalled */ |
71 | int eos_signalled; |
72 | |
73 | /** end of sequence pulled */ |
74 | int eos_pulled; |
75 | |
76 | /* counter for frames submitted to encoder, used as dts */ |
77 | int64_t dts; |
78 | |
79 | /** enable noarith */ |
80 | int noarith; |
81 | } SchroEncoderParams; |
82 | |
83 | /** |
84 | * Works out Schro-compatible chroma format. |
85 | */ |
86 | static int set_chroma_format(AVCodecContext *avctx) |
87 | { |
88 | int num_formats = sizeof(schro_pixel_format_map) / |
89 | sizeof(schro_pixel_format_map[0]); |
90 | int idx; |
91 | |
92 | SchroEncoderParams *p_schro_params = avctx->priv_data; |
93 | |
94 | for (idx = 0; idx < num_formats; ++idx) { |
95 | if (schro_pixel_format_map[idx].ff_pix_fmt == avctx->pix_fmt) { |
96 | p_schro_params->format->chroma_format = |
97 | schro_pixel_format_map[idx].schro_pix_fmt; |
98 | return 0; |
99 | } |
100 | } |
101 | |
102 | av_log(avctx, AV_LOG_ERROR, |
103 | "This codec currently only supports planar YUV 4:2:0, 4:2:2" |
104 | " and 4:4:4 formats.\n"); |
105 | |
106 | return -1; |
107 | } |
108 | |
109 | static av_cold int libschroedinger_encode_init(AVCodecContext *avctx) |
110 | { |
111 | SchroEncoderParams *p_schro_params = avctx->priv_data; |
112 | SchroVideoFormatEnum preset; |
113 | |
114 | /* Initialize the libraries that libschroedinger depends on. */ |
115 | schro_init(); |
116 | |
117 | /* Create an encoder object. */ |
118 | p_schro_params->encoder = schro_encoder_new(); |
119 | |
120 | if (!p_schro_params->encoder) { |
121 | av_log(avctx, AV_LOG_ERROR, |
122 | "Unrecoverable Error: schro_encoder_new failed. "); |
123 | return -1; |
124 | } |
125 | |
126 | /* Initialize the format. */ |
127 | preset = ff_get_schro_video_format_preset(avctx); |
128 | p_schro_params->format = |
129 | schro_encoder_get_video_format(p_schro_params->encoder); |
130 | schro_video_format_set_std_video_format(p_schro_params->format, preset); |
131 | p_schro_params->format->width = avctx->width; |
132 | p_schro_params->format->height = avctx->height; |
133 | |
134 | if (set_chroma_format(avctx) == -1) |
135 | return -1; |
136 | |
137 | if (avctx->color_primaries == AVCOL_PRI_BT709) { |
138 | p_schro_params->format->colour_primaries = SCHRO_COLOUR_PRIMARY_HDTV; |
139 | } else if (avctx->color_primaries == AVCOL_PRI_BT470BG) { |
140 | p_schro_params->format->colour_primaries = SCHRO_COLOUR_PRIMARY_SDTV_625; |
141 | } else if (avctx->color_primaries == AVCOL_PRI_SMPTE170M) { |
142 | p_schro_params->format->colour_primaries = SCHRO_COLOUR_PRIMARY_SDTV_525; |
143 | } |
144 | |
145 | if (avctx->colorspace == AVCOL_SPC_BT709) { |
146 | p_schro_params->format->colour_matrix = SCHRO_COLOUR_MATRIX_HDTV; |
147 | } else if (avctx->colorspace == AVCOL_SPC_BT470BG) { |
148 | p_schro_params->format->colour_matrix = SCHRO_COLOUR_MATRIX_SDTV; |
149 | } |
150 | |
151 | if (avctx->color_trc == AVCOL_TRC_BT709) { |
152 | p_schro_params->format->transfer_function = SCHRO_TRANSFER_CHAR_TV_GAMMA; |
153 | } |
154 | |
155 | if (ff_get_schro_frame_format(p_schro_params->format->chroma_format, |
156 | &p_schro_params->frame_format) == -1) { |
157 | av_log(avctx, AV_LOG_ERROR, |
158 | "This codec currently supports only planar YUV 4:2:0, 4:2:2" |
159 | " and 4:4:4 formats.\n"); |
160 | return -1; |
161 | } |
162 | |
163 | p_schro_params->format->frame_rate_numerator = avctx->time_base.den; |
164 | p_schro_params->format->frame_rate_denominator = avctx->time_base.num; |
165 | |
166 | p_schro_params->frame_size = av_image_get_buffer_size(avctx->pix_fmt, |
167 | avctx->width, |
168 | avctx->height, 1); |
169 | |
170 | if (!avctx->gop_size) { |
171 | schro_encoder_setting_set_double(p_schro_params->encoder, |
172 | "gop_structure", |
173 | SCHRO_ENCODER_GOP_INTRA_ONLY); |
174 | |
175 | #if FF_API_CODER_TYPE |
176 | FF_DISABLE_DEPRECATION_WARNINGS |
177 | if (avctx->coder_type != FF_CODER_TYPE_VLC) |
178 | p_schro_params->noarith = 0; |
179 | FF_ENABLE_DEPRECATION_WARNINGS |
180 | #endif |
181 | schro_encoder_setting_set_double(p_schro_params->encoder, |
182 | "enable_noarith", |
183 | p_schro_params->noarith); |
184 | } else { |
185 | schro_encoder_setting_set_double(p_schro_params->encoder, |
186 | "au_distance", avctx->gop_size); |
187 | avctx->has_b_frames = 1; |
188 | p_schro_params->dts = -1; |
189 | } |
190 | |
191 | /* FIXME - Need to handle SCHRO_ENCODER_RATE_CONTROL_LOW_DELAY. */ |
192 | if (avctx->flags & AV_CODEC_FLAG_QSCALE) { |
193 | if (!avctx->global_quality) { |
194 | /* lossless coding */ |
195 | schro_encoder_setting_set_double(p_schro_params->encoder, |
196 | "rate_control", |
197 | SCHRO_ENCODER_RATE_CONTROL_LOSSLESS); |
198 | } else { |
199 | int quality; |
200 | schro_encoder_setting_set_double(p_schro_params->encoder, |
201 | "rate_control", |
202 | SCHRO_ENCODER_RATE_CONTROL_CONSTANT_QUALITY); |
203 | |
204 | quality = avctx->global_quality / FF_QP2LAMBDA; |
205 | if (quality > 10) |
206 | quality = 10; |
207 | schro_encoder_setting_set_double(p_schro_params->encoder, |
208 | "quality", quality); |
209 | } |
210 | } else { |
211 | schro_encoder_setting_set_double(p_schro_params->encoder, |
212 | "rate_control", |
213 | SCHRO_ENCODER_RATE_CONTROL_CONSTANT_BITRATE); |
214 | |
215 | schro_encoder_setting_set_double(p_schro_params->encoder, |
216 | "bitrate", avctx->bit_rate); |
217 | } |
218 | |
219 | if (avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) |
220 | /* All material can be coded as interlaced or progressive |
221 | irrespective of the type of source material. */ |
222 | schro_encoder_setting_set_double(p_schro_params->encoder, |
223 | "interlaced_coding", 1); |
224 | |
225 | schro_encoder_setting_set_double(p_schro_params->encoder, "open_gop", |
226 | !(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP)); |
227 | |
228 | /* FIXME: Signal range hardcoded to 8-bit data until both libschroedinger |
229 | * and libdirac support other bit-depth data. */ |
230 | schro_video_format_set_std_signal_range(p_schro_params->format, |
231 | SCHRO_SIGNAL_RANGE_8BIT_VIDEO); |
232 | |
233 | /* Set the encoder format. */ |
234 | schro_encoder_set_video_format(p_schro_params->encoder, |
235 | p_schro_params->format); |
236 | |
237 | /* Set the debug level. */ |
238 | schro_debug_set_level(avctx->debug); |
239 | |
240 | schro_encoder_start(p_schro_params->encoder); |
241 | |
242 | /* Initialize the encoded frame queue. */ |
243 | ff_schro_queue_init(&p_schro_params->enc_frame_queue); |
244 | return 0; |
245 | } |
246 | |
247 | static SchroFrame *libschroedinger_frame_from_data(AVCodecContext *avctx, |
248 | const AVFrame *frame) |
249 | { |
250 | SchroEncoderParams *p_schro_params = avctx->priv_data; |
251 | SchroFrame *in_frame = ff_create_schro_frame(avctx, |
252 | p_schro_params->frame_format); |
253 | |
254 | if (in_frame) { |
255 | /* Copy input data to SchroFrame buffers (they match the ones |
256 | * referenced by the AVFrame stored in priv) */ |
257 | if (av_frame_copy(in_frame->priv, frame) < 0) { |
258 | av_log(avctx, AV_LOG_ERROR, "Failed to copy input data\n"); |
259 | return NULL; |
260 | } |
261 | } |
262 | |
263 | return in_frame; |
264 | } |
265 | |
266 | static void libschroedinger_free_frame(void *data) |
267 | { |
268 | FFSchroEncodedFrame *enc_frame = data; |
269 | |
270 | av_freep(&enc_frame->p_encbuf); |
271 | av_free(enc_frame); |
272 | } |
273 | |
274 | static int libschroedinger_encode_frame(AVCodecContext *avctx, AVPacket *pkt, |
275 | const AVFrame *frame, int *got_packet) |
276 | { |
277 | int enc_size = 0; |
278 | SchroEncoderParams *p_schro_params = avctx->priv_data; |
279 | SchroEncoder *encoder = p_schro_params->encoder; |
280 | struct FFSchroEncodedFrame *p_frame_output = NULL; |
281 | int go = 1; |
282 | SchroBuffer *enc_buf; |
283 | int presentation_frame; |
284 | int parse_code; |
285 | int last_frame_in_sequence = 0; |
286 | int pkt_size, ret; |
287 | |
288 | if (!frame) { |
289 | /* Push end of sequence if not already signalled. */ |
290 | if (!p_schro_params->eos_signalled) { |
291 | schro_encoder_end_of_stream(encoder); |
292 | p_schro_params->eos_signalled = 1; |
293 | } |
294 | } else { |
295 | /* Allocate frame data to schro input buffer. */ |
296 | SchroFrame *in_frame = libschroedinger_frame_from_data(avctx, frame); |
297 | if (!in_frame) |
298 | return AVERROR(ENOMEM); |
299 | /* Load next frame. */ |
300 | schro_encoder_push_frame(encoder, in_frame); |
301 | } |
302 | |
303 | if (p_schro_params->eos_pulled) |
304 | go = 0; |
305 | |
306 | /* Now check to see if we have any output from the encoder. */ |
307 | while (go) { |
308 | int err; |
309 | SchroStateEnum state; |
310 | state = schro_encoder_wait(encoder); |
311 | switch (state) { |
312 | case SCHRO_STATE_HAVE_BUFFER: |
313 | case SCHRO_STATE_END_OF_STREAM: |
314 | enc_buf = schro_encoder_pull(encoder, &presentation_frame); |
315 | if (enc_buf->length <= 0) |
316 | return AVERROR_BUG; |
317 | parse_code = enc_buf->data[4]; |
318 | |
319 | /* All non-frame data is prepended to actual frame data to |
320 | * be able to set the pts correctly. So we don't write data |
321 | * to the frame output queue until we actually have a frame |
322 | */ |
323 | if ((err = av_reallocp(&p_schro_params->enc_buf, |
324 | p_schro_params->enc_buf_size + |
325 | enc_buf->length)) < 0) { |
326 | p_schro_params->enc_buf_size = 0; |
327 | return err; |
328 | } |
329 | |
330 | memcpy(p_schro_params->enc_buf + p_schro_params->enc_buf_size, |
331 | enc_buf->data, enc_buf->length); |
332 | p_schro_params->enc_buf_size += enc_buf->length; |
333 | |
334 | |
335 | if (state == SCHRO_STATE_END_OF_STREAM) { |
336 | p_schro_params->eos_pulled = 1; |
337 | go = 0; |
338 | } |
339 | |
340 | if (!SCHRO_PARSE_CODE_IS_PICTURE(parse_code)) { |
341 | schro_buffer_unref(enc_buf); |
342 | break; |
343 | } |
344 | |
345 | /* Create output frame. */ |
346 | p_frame_output = av_mallocz(sizeof(FFSchroEncodedFrame)); |
347 | if (!p_frame_output) |
348 | return AVERROR(ENOMEM); |
349 | /* Set output data. */ |
350 | p_frame_output->size = p_schro_params->enc_buf_size; |
351 | p_frame_output->p_encbuf = p_schro_params->enc_buf; |
352 | if (SCHRO_PARSE_CODE_IS_INTRA(parse_code) && |
353 | SCHRO_PARSE_CODE_IS_REFERENCE(parse_code)) |
354 | p_frame_output->key_frame = 1; |
355 | |
356 | /* Parse the coded frame number from the bitstream. Bytes 14 |
357 | * through 17 represent the frame number. */ |
358 | p_frame_output->frame_num = AV_RB32(enc_buf->data + 13); |
359 | |
360 | ff_schro_queue_push_back(&p_schro_params->enc_frame_queue, |
361 | p_frame_output); |
362 | p_schro_params->enc_buf_size = 0; |
363 | p_schro_params->enc_buf = NULL; |
364 | |
365 | schro_buffer_unref(enc_buf); |
366 | |
367 | break; |
368 | |
369 | case SCHRO_STATE_NEED_FRAME: |
370 | go = 0; |
371 | break; |
372 | |
373 | case SCHRO_STATE_AGAIN: |
374 | break; |
375 | |
376 | default: |
377 | av_log(avctx, AV_LOG_ERROR, "Unknown Schro Encoder state\n"); |
378 | return -1; |
379 | } |
380 | } |
381 | |
382 | /* Copy 'next' frame in queue. */ |
383 | |
384 | if (p_schro_params->enc_frame_queue.size == 1 && |
385 | p_schro_params->eos_pulled) |
386 | last_frame_in_sequence = 1; |
387 | |
388 | p_frame_output = ff_schro_queue_pop(&p_schro_params->enc_frame_queue); |
389 | |
390 | if (!p_frame_output) |
391 | return 0; |
392 | |
393 | pkt_size = p_frame_output->size; |
394 | if (last_frame_in_sequence && p_schro_params->enc_buf_size > 0) |
395 | pkt_size += p_schro_params->enc_buf_size; |
396 | if ((ret = ff_alloc_packet2(avctx, pkt, pkt_size, 0)) < 0) |
397 | goto error; |
398 | |
399 | memcpy(pkt->data, p_frame_output->p_encbuf, p_frame_output->size); |
400 | #if FF_API_CODED_FRAME |
401 | FF_DISABLE_DEPRECATION_WARNINGS |
402 | avctx->coded_frame->key_frame = p_frame_output->key_frame; |
403 | avctx->coded_frame->pts = p_frame_output->frame_num; |
404 | FF_ENABLE_DEPRECATION_WARNINGS |
405 | #endif |
406 | /* Use the frame number of the encoded frame as the pts. It is OK to |
407 | * do so since Dirac is a constant frame rate codec. It expects input |
408 | * to be of constant frame rate. */ |
409 | pkt->pts = p_frame_output->frame_num; |
410 | pkt->dts = p_schro_params->dts++; |
411 | enc_size = p_frame_output->size; |
412 | |
413 | /* Append the end of sequence information to the last frame in the |
414 | * sequence. */ |
415 | if (last_frame_in_sequence && p_schro_params->enc_buf_size > 0) { |
416 | memcpy(pkt->data + enc_size, p_schro_params->enc_buf, |
417 | p_schro_params->enc_buf_size); |
418 | enc_size += p_schro_params->enc_buf_size; |
419 | av_freep(&p_schro_params->enc_buf); |
420 | p_schro_params->enc_buf_size = 0; |
421 | } |
422 | |
423 | if (p_frame_output->key_frame) |
424 | pkt->flags |= AV_PKT_FLAG_KEY; |
425 | *got_packet = 1; |
426 | |
427 | error: |
428 | /* free frame */ |
429 | libschroedinger_free_frame(p_frame_output); |
430 | return ret; |
431 | } |
432 | |
433 | |
434 | static int libschroedinger_encode_close(AVCodecContext *avctx) |
435 | { |
436 | SchroEncoderParams *p_schro_params = avctx->priv_data; |
437 | |
438 | /* Close the encoder. */ |
439 | schro_encoder_free(p_schro_params->encoder); |
440 | |
441 | /* Free data in the output frame queue. */ |
442 | ff_schro_queue_free(&p_schro_params->enc_frame_queue, |
443 | libschroedinger_free_frame); |
444 | |
445 | |
446 | /* Free the encoder buffer. */ |
447 | if (p_schro_params->enc_buf_size) |
448 | av_freep(&p_schro_params->enc_buf); |
449 | |
450 | /* Free the video format structure. */ |
451 | av_freep(&p_schro_params->format); |
452 | |
453 | return 0; |
454 | } |
455 | |
456 | #define OFFSET(x) offsetof(SchroEncoderParams, x) |
457 | #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM |
458 | static const AVOption options[] = { |
459 | { "noarith", "Enable noarith", OFFSET(noarith), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, |
460 | |
461 | { NULL }, |
462 | }; |
463 | |
464 | static const AVClass libschroedinger_class = { |
465 | .class_name = "libschroedinger", |
466 | .item_name = av_default_item_name, |
467 | .option = options, |
468 | .version = LIBAVUTIL_VERSION_INT, |
469 | }; |
470 | |
471 | AVCodec ff_libschroedinger_encoder = { |
472 | .name = "libschroedinger", |
473 | .long_name = NULL_IF_CONFIG_SMALL("libschroedinger Dirac 2.2"), |
474 | .type = AVMEDIA_TYPE_VIDEO, |
475 | .id = AV_CODEC_ID_DIRAC, |
476 | .priv_data_size = sizeof(SchroEncoderParams), |
477 | .priv_class = &libschroedinger_class, |
478 | .init = libschroedinger_encode_init, |
479 | .encode2 = libschroedinger_encode_frame, |
480 | .close = libschroedinger_encode_close, |
481 | .capabilities = AV_CODEC_CAP_DELAY, |
482 | .pix_fmts = (const enum AVPixelFormat[]){ |
483 | AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE |
484 | }, |
485 | }; |
486 |