annotate ffmpeg/libavcodec/libschroedingerenc.c @ 13:844d341cf643 tip

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