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

libavcodec/libdiracdec.c

Go to the documentation of this file.
00001 /*
00002  * Dirac decoder support via libdirac library
00003  * Copyright (c) 2005 BBC, Andrew Kennedy <dirac at rd dot bbc dot co dot uk>
00004  * Copyright (c) 2006-2008 BBC, Anuradha Suraparaju <asuraparaju at gmail dot com >
00005  *
00006  * This file is part of FFmpeg.
00007  *
00008  * FFmpeg is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * FFmpeg is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with FFmpeg; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00021  */
00022 
00031 #include "libdirac.h"
00032 
00033 #undef NDEBUG
00034 #include <assert.h>
00035 
00036 #include <libdirac_decoder/dirac_parser.h>
00037 
00039 typedef struct FfmpegDiracDecoderParams {
00041     dirac_decoder_t* p_decoder;
00042 
00044     unsigned char* p_out_frame_buf;
00045 } FfmpegDiracDecoderParams;
00046 
00047 
00051 static enum PixelFormat GetFfmpegChromaFormat(dirac_chroma_t dirac_pix_fmt)
00052 {
00053     int num_formats = sizeof(ffmpeg_dirac_pixel_format_map) /
00054                       sizeof(ffmpeg_dirac_pixel_format_map[0]);
00055     int idx;
00056 
00057     for (idx = 0; idx < num_formats; ++idx)
00058         if (ffmpeg_dirac_pixel_format_map[idx].dirac_pix_fmt == dirac_pix_fmt)
00059             return ffmpeg_dirac_pixel_format_map[idx].ff_pix_fmt;
00060     return PIX_FMT_NONE;
00061 }
00062 
00063 static av_cold int libdirac_decode_init(AVCodecContext *avccontext)
00064 {
00065 
00066     FfmpegDiracDecoderParams *p_dirac_params = avccontext->priv_data;
00067     p_dirac_params->p_decoder =  dirac_decoder_init(avccontext->debug);
00068 
00069     if (!p_dirac_params->p_decoder)
00070         return -1;
00071 
00072     return 0;
00073 }
00074 
00075 static int libdirac_decode_frame(AVCodecContext *avccontext,
00076                                  void *data, int *data_size,
00077                                  AVPacket *avpkt)
00078 {
00079     const uint8_t *buf = avpkt->data;
00080     int buf_size = avpkt->size;
00081 
00082     FfmpegDiracDecoderParams *p_dirac_params = avccontext->priv_data;
00083     AVPicture *picture = data;
00084     AVPicture pic;
00085     int pict_size;
00086     unsigned char *buffer[3];
00087 
00088     *data_size = 0;
00089 
00090     if (buf_size > 0) {
00091         /* set data to decode into buffer */
00092         dirac_buffer(p_dirac_params->p_decoder, buf, buf + buf_size);
00093         if ((buf[4] & 0x08) == 0x08 && (buf[4] & 0x03))
00094             avccontext->has_b_frames = 1;
00095     }
00096     while (1) {
00097          /* parse data and process result */
00098         DecoderState state = dirac_parse(p_dirac_params->p_decoder);
00099         switch (state) {
00100         case STATE_BUFFER:
00101             return buf_size;
00102 
00103         case STATE_SEQUENCE:
00104         {
00105             /* tell FFmpeg about sequence details */
00106             dirac_sourceparams_t *src_params = &p_dirac_params->p_decoder->src_params;
00107 
00108             if (avcodec_check_dimensions(avccontext, src_params->width,
00109                                          src_params->height) < 0) {
00110                 av_log(avccontext, AV_LOG_ERROR, "Invalid dimensions (%dx%d)\n",
00111                        src_params->width, src_params->height);
00112                 avccontext->height = avccontext->width = 0;
00113                 return -1;
00114             }
00115 
00116             avccontext->height = src_params->height;
00117             avccontext->width  = src_params->width;
00118 
00119             avccontext->pix_fmt = GetFfmpegChromaFormat(src_params->chroma);
00120             if (avccontext->pix_fmt == PIX_FMT_NONE) {
00121                 av_log(avccontext, AV_LOG_ERROR,
00122                        "Dirac chroma format %d not supported currently\n",
00123                        src_params->chroma);
00124                 return -1;
00125             }
00126 
00127             avccontext->time_base.den = src_params->frame_rate.numerator;
00128             avccontext->time_base.num = src_params->frame_rate.denominator;
00129 
00130             /* calculate output dimensions */
00131             avpicture_fill(&pic, NULL, avccontext->pix_fmt,
00132                            avccontext->width, avccontext->height);
00133 
00134             pict_size = avpicture_get_size(avccontext->pix_fmt,
00135                                            avccontext->width,
00136                                            avccontext->height);
00137 
00138             /* allocate output buffer */
00139             if (!p_dirac_params->p_out_frame_buf)
00140                 p_dirac_params->p_out_frame_buf = av_malloc(pict_size);
00141             buffer[0] = p_dirac_params->p_out_frame_buf;
00142             buffer[1] = p_dirac_params->p_out_frame_buf +
00143                         pic.linesize[0] * avccontext->height;
00144             buffer[2] = buffer[1] +
00145                         pic.linesize[1] * src_params->chroma_height;
00146 
00147             /* tell Dirac about output destination */
00148             dirac_set_buf(p_dirac_params->p_decoder, buffer, NULL);
00149             break;
00150         }
00151         case STATE_SEQUENCE_END:
00152             break;
00153 
00154         case STATE_PICTURE_AVAIL:
00155             /* fill picture with current buffer data from Dirac */
00156             avpicture_fill(picture, p_dirac_params->p_out_frame_buf,
00157                            avccontext->pix_fmt,
00158                            avccontext->width, avccontext->height);
00159             *data_size = sizeof(AVPicture);
00160             return buf_size;
00161 
00162         case STATE_INVALID:
00163             return -1;
00164 
00165         default:
00166             break;
00167         }
00168     }
00169 
00170     return buf_size;
00171 }
00172 
00173 
00174 static av_cold int libdirac_decode_close(AVCodecContext *avccontext)
00175 {
00176     FfmpegDiracDecoderParams *p_dirac_params = avccontext->priv_data;
00177     dirac_decoder_close(p_dirac_params->p_decoder);
00178 
00179     av_freep(&p_dirac_params->p_out_frame_buf);
00180 
00181     return 0;
00182 }
00183 
00184 static void libdirac_flush(AVCodecContext *avccontext)
00185 {
00186     /* Got a seek request. We will need free memory held in the private
00187      * context and free the current Dirac decoder handle and then open
00188      * a new decoder handle. */
00189     libdirac_decode_close(avccontext);
00190     libdirac_decode_init(avccontext);
00191     return;
00192 }
00193 
00194 
00195 
00196 AVCodec libdirac_decoder = {
00197     "libdirac",
00198     AVMEDIA_TYPE_VIDEO,
00199     CODEC_ID_DIRAC,
00200     sizeof(FfmpegDiracDecoderParams),
00201     libdirac_decode_init,
00202     NULL,
00203     libdirac_decode_close,
00204     libdirac_decode_frame,
00205     CODEC_CAP_DELAY,
00206     .flush = libdirac_flush,
00207     .long_name = NULL_IF_CONFIG_SMALL("libdirac Dirac 2.2"),
00208 };

Generated on Fri Sep 16 2011 17:17:38 for FFmpeg by  doxygen 1.7.1