• 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
00040 {
00042     dirac_decoder_t* p_decoder;
00043 
00045     unsigned char* p_out_frame_buf;
00046 } FfmpegDiracDecoderParams;
00047 
00048 
00052 static enum PixelFormat GetFfmpegChromaFormat(dirac_chroma_t dirac_pix_fmt)
00053 {
00054     int num_formats = sizeof(ffmpeg_dirac_pixel_format_map) /
00055                       sizeof(ffmpeg_dirac_pixel_format_map[0]);
00056     int idx;
00057 
00058     for (idx = 0; idx < num_formats; ++idx) {
00059         if (ffmpeg_dirac_pixel_format_map[idx].dirac_pix_fmt == dirac_pix_fmt) {
00060             return ffmpeg_dirac_pixel_format_map[idx].ff_pix_fmt;
00061         }
00062     }
00063     return PIX_FMT_NONE;
00064 }
00065 
00066 static av_cold int libdirac_decode_init(AVCodecContext *avccontext)
00067 {
00068 
00069     FfmpegDiracDecoderParams *p_dirac_params = avccontext->priv_data ;
00070     p_dirac_params->p_decoder =  dirac_decoder_init(avccontext->debug);
00071 
00072     if (!p_dirac_params->p_decoder)
00073         return -1;
00074 
00075     return 0 ;
00076 }
00077 
00078 static int libdirac_decode_frame(AVCodecContext *avccontext,
00079                                  void *data, int *data_size,
00080                                  const uint8_t *buf, int buf_size)
00081 {
00082 
00083     FfmpegDiracDecoderParams *p_dirac_params = avccontext->priv_data;
00084     AVPicture *picture = data;
00085     AVPicture pic;
00086     int pict_size;
00087     unsigned char *buffer[3];
00088 
00089     *data_size = 0;
00090 
00091     if (buf_size>0) {
00092         /* set data to decode into buffer */
00093         dirac_buffer (p_dirac_params->p_decoder, buf, buf+buf_size);
00094         if ((buf[4] &0x08) == 0x08 && (buf[4] & 0x03))
00095             avccontext->has_b_frames = 1;
00096     }
00097     while (1) {
00098          /* parse data and process result */
00099         DecoderState state = dirac_parse (p_dirac_params->p_decoder);
00100         switch (state)
00101         {
00102         case STATE_BUFFER:
00103             return buf_size;
00104 
00105         case STATE_SEQUENCE:
00106         {
00107             /* tell FFmpeg about sequence details */
00108             dirac_sourceparams_t *src_params =
00109                                   &p_dirac_params->p_decoder->src_params;
00110 
00111             if (avcodec_check_dimensions(avccontext, src_params->width,
00112                                          src_params->height) < 0) {
00113                 av_log(avccontext, AV_LOG_ERROR, "Invalid dimensions (%dx%d)\n",
00114                        src_params->width, src_params->height);
00115                 avccontext->height = avccontext->width = 0;
00116                 return -1;
00117             }
00118 
00119             avccontext->height = src_params->height;
00120             avccontext->width  = src_params->width;
00121 
00122             avccontext->pix_fmt = GetFfmpegChromaFormat(src_params->chroma);
00123             if (avccontext->pix_fmt == PIX_FMT_NONE) {
00124                 av_log (avccontext, AV_LOG_ERROR,
00125                         "Dirac chroma format %d not supported currently\n",
00126                         src_params->chroma);
00127                 return -1;
00128             }
00129 
00130             avccontext->time_base.den = src_params->frame_rate.numerator;
00131             avccontext->time_base.num = src_params->frame_rate.denominator;
00132 
00133             /* calculate output dimensions */
00134             avpicture_fill(&pic, NULL, avccontext->pix_fmt,
00135                            avccontext->width, avccontext->height);
00136 
00137             pict_size = avpicture_get_size(avccontext->pix_fmt,
00138                                            avccontext->width,
00139                                            avccontext->height);
00140 
00141             /* allocate output buffer */
00142             if (p_dirac_params->p_out_frame_buf == NULL)
00143                 p_dirac_params->p_out_frame_buf = av_malloc (pict_size);
00144             buffer[0] = p_dirac_params->p_out_frame_buf;
00145             buffer[1] = p_dirac_params->p_out_frame_buf +
00146                         pic.linesize[0] * avccontext->height;
00147             buffer[2] = buffer[1] +
00148                         pic.linesize[1] * src_params->chroma_height;
00149 
00150             /* tell Dirac about output destination */
00151             dirac_set_buf(p_dirac_params->p_decoder, buffer, NULL);
00152             break;
00153         }
00154         case STATE_SEQUENCE_END:
00155             break;
00156 
00157         case STATE_PICTURE_AVAIL:
00158             /* fill picture with current buffer data from Dirac */
00159             avpicture_fill(picture, p_dirac_params->p_out_frame_buf,
00160                            avccontext->pix_fmt,
00161                            avccontext->width, avccontext->height);
00162             *data_size = sizeof(AVPicture);
00163             return buf_size;
00164 
00165         case STATE_INVALID:
00166             return -1;
00167 
00168         default:
00169             break;
00170         }
00171     }
00172 
00173     return buf_size;
00174 }
00175 
00176 
00177 static av_cold int libdirac_decode_close(AVCodecContext *avccontext)
00178 {
00179     FfmpegDiracDecoderParams *p_dirac_params = avccontext->priv_data;
00180     dirac_decoder_close (p_dirac_params->p_decoder);
00181 
00182     av_freep(&p_dirac_params->p_out_frame_buf);
00183 
00184     return 0 ;
00185 }
00186 
00187 static void libdirac_flush (AVCodecContext *avccontext)
00188 {
00189     /* Got a seek request. We will need free memory held in the private
00190      * context and free the current Dirac decoder handle and then open
00191      * a new decoder handle. */
00192     libdirac_decode_close (avccontext);
00193     libdirac_decode_init (avccontext);
00194     return;
00195 }
00196 
00197 
00198 
00199 AVCodec libdirac_decoder = {
00200     "libdirac",
00201     CODEC_TYPE_VIDEO,
00202     CODEC_ID_DIRAC,
00203     sizeof(FfmpegDiracDecoderParams),
00204     libdirac_decode_init,
00205     NULL,
00206     libdirac_decode_close,
00207     libdirac_decode_frame,
00208     CODEC_CAP_DELAY,
00209     .flush = libdirac_flush,
00210     .long_name = NULL_IF_CONFIG_SMALL("libdirac Dirac 2.2"),
00211 } ;

Generated on Sat Feb 16 2013 09:23:12 for ffmpeg by  doxygen 1.7.1