• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavcodec/libschroedingerenc.c

Go to the documentation of this file.
00001 /*
00002  * Dirac encoder support via Schroedinger libraries
00003  * Copyright (c) 2008 BBC, Anuradha Suraparaju <asuraparaju at gmail dot com >
00004  *
00005  * This file is part of Libav.
00006  *
00007  * Libav is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * Libav is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with Libav; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00030 #undef NDEBUG
00031 #include <assert.h>
00032 
00033 #include <schroedinger/schro.h>
00034 #include <schroedinger/schrodebug.h>
00035 #include <schroedinger/schrovideoformat.h>
00036 
00037 #include "avcodec.h"
00038 #include "libdirac_libschro.h"
00039 #include "libschroedinger.h"
00040 #include "bytestream.h"
00041 
00042 
00044 typedef struct SchroEncoderParams {
00046     SchroVideoFormat *format;
00047 
00049     SchroFrameFormat frame_format;
00050 
00052     AVFrame picture;
00053 
00055     int frame_size;
00056 
00058     SchroEncoder* encoder;
00059 
00061     unsigned char *enc_buf;
00062 
00064     int enc_buf_size;
00065 
00067     DiracSchroQueue enc_frame_queue;
00068 
00070     int eos_signalled;
00071 
00073     int eos_pulled;
00074 } SchroEncoderParams;
00075 
00079 static int SetSchroChromaFormat(AVCodecContext *avccontext)
00080 {
00081     int num_formats = sizeof(schro_pixel_format_map) /
00082                       sizeof(schro_pixel_format_map[0]);
00083     int idx;
00084 
00085     SchroEncoderParams *p_schro_params = avccontext->priv_data;
00086 
00087     for (idx = 0; idx < num_formats; ++idx) {
00088         if (schro_pixel_format_map[idx].ff_pix_fmt ==
00089             avccontext->pix_fmt) {
00090             p_schro_params->format->chroma_format =
00091                             schro_pixel_format_map[idx].schro_pix_fmt;
00092             return 0;
00093         }
00094     }
00095 
00096     av_log(avccontext, AV_LOG_ERROR,
00097            "This codec currently only supports planar YUV 4:2:0, 4:2:2"
00098            " and 4:4:4 formats.\n");
00099 
00100     return -1;
00101 }
00102 
00103 static int libschroedinger_encode_init(AVCodecContext *avccontext)
00104 {
00105     SchroEncoderParams *p_schro_params = avccontext->priv_data;
00106     SchroVideoFormatEnum preset;
00107 
00108     /* Initialize the libraries that libschroedinger depends on. */
00109     schro_init();
00110 
00111     /* Create an encoder object. */
00112     p_schro_params->encoder = schro_encoder_new();
00113 
00114     if (!p_schro_params->encoder) {
00115         av_log(avccontext, AV_LOG_ERROR,
00116                "Unrecoverable Error: schro_encoder_new failed. ");
00117         return -1;
00118     }
00119 
00120     /* Initialize the format. */
00121     preset = ff_get_schro_video_format_preset(avccontext);
00122     p_schro_params->format =
00123                     schro_encoder_get_video_format(p_schro_params->encoder);
00124     schro_video_format_set_std_video_format(p_schro_params->format, preset);
00125     p_schro_params->format->width  = avccontext->width;
00126     p_schro_params->format->height = avccontext->height;
00127 
00128     if (SetSchroChromaFormat(avccontext) == -1)
00129         return -1;
00130 
00131     if (avccontext->color_primaries == AVCOL_PRI_BT709) {
00132         p_schro_params->format->colour_primaries = SCHRO_COLOUR_PRIMARY_HDTV;
00133     } else if (avccontext->color_primaries == AVCOL_PRI_BT470BG) {
00134         p_schro_params->format->colour_primaries = SCHRO_COLOUR_PRIMARY_SDTV_625;
00135     } else if (avccontext->color_primaries == AVCOL_PRI_SMPTE170M) {
00136         p_schro_params->format->colour_primaries = SCHRO_COLOUR_PRIMARY_SDTV_525;
00137     }
00138 
00139     if (avccontext->colorspace == AVCOL_SPC_BT709) {
00140         p_schro_params->format->colour_matrix = SCHRO_COLOUR_MATRIX_HDTV;
00141     } else if (avccontext->colorspace == AVCOL_SPC_BT470BG) {
00142         p_schro_params->format->colour_matrix = SCHRO_COLOUR_MATRIX_SDTV;
00143     }
00144 
00145     if (avccontext->color_trc == AVCOL_TRC_BT709) {
00146         p_schro_params->format->transfer_function = SCHRO_TRANSFER_CHAR_TV_GAMMA;
00147     }
00148 
00149     if (ff_get_schro_frame_format(p_schro_params->format->chroma_format,
00150                                   &p_schro_params->frame_format) == -1) {
00151         av_log(avccontext, AV_LOG_ERROR,
00152                "This codec currently supports only planar YUV 4:2:0, 4:2:2"
00153                " and 4:4:4 formats.\n");
00154         return -1;
00155     }
00156 
00157     p_schro_params->format->frame_rate_numerator   = avccontext->time_base.den;
00158     p_schro_params->format->frame_rate_denominator = avccontext->time_base.num;
00159 
00160     p_schro_params->frame_size = avpicture_get_size(avccontext->pix_fmt,
00161                                                     avccontext->width,
00162                                                     avccontext->height);
00163 
00164     avccontext->coded_frame = &p_schro_params->picture;
00165 
00166     if (!avccontext->gop_size) {
00167         schro_encoder_setting_set_double(p_schro_params->encoder,
00168                                          "gop_structure",
00169                                          SCHRO_ENCODER_GOP_INTRA_ONLY);
00170 
00171         if (avccontext->coder_type == FF_CODER_TYPE_VLC)
00172             schro_encoder_setting_set_double(p_schro_params->encoder,
00173                                              "enable_noarith", 1);
00174     } else {
00175         schro_encoder_setting_set_double(p_schro_params->encoder,
00176                                          "au_distance", avccontext->gop_size);
00177         avccontext->has_b_frames = 1;
00178     }
00179 
00180     /* FIXME - Need to handle SCHRO_ENCODER_RATE_CONTROL_LOW_DELAY. */
00181     if (avccontext->flags & CODEC_FLAG_QSCALE) {
00182         if (!avccontext->global_quality) {
00183             /* lossless coding */
00184             schro_encoder_setting_set_double(p_schro_params->encoder,
00185                                              "rate_control",
00186                                              SCHRO_ENCODER_RATE_CONTROL_LOSSLESS);
00187         } else {
00188             int quality;
00189             schro_encoder_setting_set_double(p_schro_params->encoder,
00190                                              "rate_control",
00191                                              SCHRO_ENCODER_RATE_CONTROL_CONSTANT_QUALITY);
00192 
00193             quality = avccontext->global_quality / FF_QP2LAMBDA;
00194             if (quality > 10)
00195                 quality = 10;
00196             schro_encoder_setting_set_double(p_schro_params->encoder,
00197                                              "quality", quality);
00198         }
00199     } else {
00200         schro_encoder_setting_set_double(p_schro_params->encoder,
00201                                          "rate_control",
00202                                          SCHRO_ENCODER_RATE_CONTROL_CONSTANT_BITRATE);
00203 
00204         schro_encoder_setting_set_double(p_schro_params->encoder,
00205                                          "bitrate",
00206                                          avccontext->bit_rate);
00207 
00208     }
00209 
00210     if (avccontext->flags & CODEC_FLAG_INTERLACED_ME)
00211         /* All material can be coded as interlaced or progressive
00212            irrespective of the type of source material. */
00213         schro_encoder_setting_set_double(p_schro_params->encoder,
00214                                          "interlaced_coding", 1);
00215 
00216     schro_encoder_setting_set_double(p_schro_params->encoder, "open_gop",
00217                                      !(avccontext->flags & CODEC_FLAG_CLOSED_GOP));
00218 
00219     /* FIXME: Signal range hardcoded to 8-bit data until both libschroedinger
00220      * and libdirac support other bit-depth data. */
00221     schro_video_format_set_std_signal_range(p_schro_params->format,
00222                                             SCHRO_SIGNAL_RANGE_8BIT_VIDEO);
00223 
00224     /* Set the encoder format. */
00225     schro_encoder_set_video_format(p_schro_params->encoder,
00226                                    p_schro_params->format);
00227 
00228     /* Set the debug level. */
00229     schro_debug_set_level(avccontext->debug);
00230 
00231     schro_encoder_start(p_schro_params->encoder);
00232 
00233     /* Initialize the encoded frame queue. */
00234     ff_dirac_schro_queue_init(&p_schro_params->enc_frame_queue);
00235     return 0;
00236 }
00237 
00238 static SchroFrame *libschroedinger_frame_from_data(AVCodecContext *avccontext,
00239                                                    void *in_data)
00240 {
00241     SchroEncoderParams *p_schro_params = avccontext->priv_data;
00242     SchroFrame *in_frame;
00243     /* Input line size may differ from what the codec supports. Especially
00244      * when transcoding from one format to another. So use avpicture_layout
00245      * to copy the frame. */
00246     in_frame = ff_create_schro_frame(avccontext, p_schro_params->frame_format);
00247 
00248     if (in_frame)
00249         avpicture_layout((AVPicture *)in_data, avccontext->pix_fmt,
00250                           avccontext->width, avccontext->height,
00251                           in_frame->components[0].data,
00252                           p_schro_params->frame_size);
00253 
00254     return in_frame;
00255 }
00256 
00257 static void SchroedingerFreeFrame(void *data)
00258 {
00259     DiracSchroEncodedFrame *enc_frame = data;
00260 
00261     av_freep(&enc_frame->p_encbuf);
00262     av_free(enc_frame);
00263 }
00264 
00265 static int libschroedinger_encode_frame(AVCodecContext *avccontext,
00266                                         unsigned char *frame,
00267                                         int buf_size, void *data)
00268 {
00269     int enc_size = 0;
00270     SchroEncoderParams *p_schro_params = avccontext->priv_data;
00271     SchroEncoder *encoder = p_schro_params->encoder;
00272     struct DiracSchroEncodedFrame *p_frame_output = NULL;
00273     int go = 1;
00274     SchroBuffer *enc_buf;
00275     int presentation_frame;
00276     int parse_code;
00277     int last_frame_in_sequence = 0;
00278 
00279     if (!data) {
00280         /* Push end of sequence if not already signalled. */
00281         if (!p_schro_params->eos_signalled) {
00282             schro_encoder_end_of_stream(encoder);
00283             p_schro_params->eos_signalled = 1;
00284         }
00285     } else {
00286         /* Allocate frame data to schro input buffer. */
00287         SchroFrame *in_frame = libschroedinger_frame_from_data(avccontext,
00288                                                                data);
00289         /* Load next frame. */
00290         schro_encoder_push_frame(encoder, in_frame);
00291     }
00292 
00293     if (p_schro_params->eos_pulled)
00294         go = 0;
00295 
00296     /* Now check to see if we have any output from the encoder. */
00297     while (go) {
00298         SchroStateEnum state;
00299         state = schro_encoder_wait(encoder);
00300         switch (state) {
00301         case SCHRO_STATE_HAVE_BUFFER:
00302         case SCHRO_STATE_END_OF_STREAM:
00303             enc_buf = schro_encoder_pull(encoder, &presentation_frame);
00304             assert(enc_buf->length > 0);
00305             assert(enc_buf->length <= buf_size);
00306             parse_code = enc_buf->data[4];
00307 
00308             /* All non-frame data is prepended to actual frame data to
00309              * be able to set the pts correctly. So we don't write data
00310              * to the frame output queue until we actually have a frame
00311              */
00312             p_schro_params->enc_buf = av_realloc(p_schro_params->enc_buf,
00313                                                  p_schro_params->enc_buf_size + enc_buf->length);
00314 
00315             memcpy(p_schro_params->enc_buf + p_schro_params->enc_buf_size,
00316                    enc_buf->data, enc_buf->length);
00317             p_schro_params->enc_buf_size += enc_buf->length;
00318 
00319 
00320             if (state == SCHRO_STATE_END_OF_STREAM) {
00321                 p_schro_params->eos_pulled = 1;
00322                 go = 0;
00323             }
00324 
00325             if (!SCHRO_PARSE_CODE_IS_PICTURE(parse_code)) {
00326                 schro_buffer_unref(enc_buf);
00327                 break;
00328             }
00329 
00330             /* Create output frame. */
00331             p_frame_output = av_mallocz(sizeof(DiracSchroEncodedFrame));
00332             /* Set output data. */
00333             p_frame_output->size     = p_schro_params->enc_buf_size;
00334             p_frame_output->p_encbuf = p_schro_params->enc_buf;
00335             if (SCHRO_PARSE_CODE_IS_INTRA(parse_code) &&
00336                 SCHRO_PARSE_CODE_IS_REFERENCE(parse_code))
00337                 p_frame_output->key_frame = 1;
00338 
00339             /* Parse the coded frame number from the bitstream. Bytes 14
00340              * through 17 represesent the frame number. */
00341             p_frame_output->frame_num = AV_RB32(enc_buf->data + 13);
00342 
00343             ff_dirac_schro_queue_push_back(&p_schro_params->enc_frame_queue,
00344                                            p_frame_output);
00345             p_schro_params->enc_buf_size = 0;
00346             p_schro_params->enc_buf      = NULL;
00347 
00348             schro_buffer_unref(enc_buf);
00349 
00350             break;
00351 
00352         case SCHRO_STATE_NEED_FRAME:
00353             go = 0;
00354             break;
00355 
00356         case SCHRO_STATE_AGAIN:
00357             break;
00358 
00359         default:
00360             av_log(avccontext, AV_LOG_ERROR, "Unknown Schro Encoder state\n");
00361             return -1;
00362         }
00363     }
00364 
00365     /* Copy 'next' frame in queue. */
00366 
00367     if (p_schro_params->enc_frame_queue.size == 1 &&
00368         p_schro_params->eos_pulled)
00369         last_frame_in_sequence = 1;
00370 
00371     p_frame_output = ff_dirac_schro_queue_pop(&p_schro_params->enc_frame_queue);
00372 
00373     if (!p_frame_output)
00374         return 0;
00375 
00376     memcpy(frame, p_frame_output->p_encbuf, p_frame_output->size);
00377     avccontext->coded_frame->key_frame = p_frame_output->key_frame;
00378     /* Use the frame number of the encoded frame as the pts. It is OK to
00379      * do so since Dirac is a constant frame rate codec. It expects input
00380      * to be of constant frame rate. */
00381     avccontext->coded_frame->pts = p_frame_output->frame_num;
00382     enc_size = p_frame_output->size;
00383 
00384     /* Append the end of sequence information to the last frame in the
00385      * sequence. */
00386     if (last_frame_in_sequence && p_schro_params->enc_buf_size > 0) {
00387         memcpy(frame + enc_size, p_schro_params->enc_buf,
00388                p_schro_params->enc_buf_size);
00389         enc_size += p_schro_params->enc_buf_size;
00390         av_freep(&p_schro_params->enc_buf);
00391         p_schro_params->enc_buf_size = 0;
00392     }
00393 
00394     /* free frame */
00395     SchroedingerFreeFrame(p_frame_output);
00396 
00397     return enc_size;
00398 }
00399 
00400 
00401 static int libschroedinger_encode_close(AVCodecContext *avccontext)
00402 {
00403     SchroEncoderParams *p_schro_params = avccontext->priv_data;
00404 
00405     /* Close the encoder. */
00406     schro_encoder_free(p_schro_params->encoder);
00407 
00408     /* Free data in the output frame queue. */
00409     ff_dirac_schro_queue_free(&p_schro_params->enc_frame_queue,
00410                               SchroedingerFreeFrame);
00411 
00412 
00413     /* Free the encoder buffer. */
00414     if (p_schro_params->enc_buf_size)
00415         av_freep(&p_schro_params->enc_buf);
00416 
00417     /* Free the video format structure. */
00418     av_freep(&p_schro_params->format);
00419 
00420     return 0;
00421 }
00422 
00423 
00424 AVCodec ff_libschroedinger_encoder = {
00425     .name           = "libschroedinger",
00426     .type           = AVMEDIA_TYPE_VIDEO,
00427     .id             = CODEC_ID_DIRAC,
00428     .priv_data_size = sizeof(SchroEncoderParams),
00429     .init           = libschroedinger_encode_init,
00430     .encode         = libschroedinger_encode_frame,
00431     .close          = libschroedinger_encode_close,
00432    .capabilities = CODEC_CAP_DELAY,
00433    .pix_fmts     = (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_NONE},
00434    .long_name    = NULL_IF_CONFIG_SMALL("libschroedinger Dirac 2.2"),
00435 };
Generated on Sun Apr 22 2012 21:54:02 for Libav by doxygen 1.7.1