Statistics
| Branch: | Revision:

ffmpeg / libavcodec / libdiracdec.c @ 72415b2a

History | View | Annotate | Download (6.71 KB)

1
/*
2
 * Dirac decoder support via libdirac library
3
 * Copyright (c) 2005 BBC, Andrew Kennedy <dirac at rd dot bbc dot co dot uk>
4
 * Copyright (c) 2006-2008 BBC, Anuradha Suraparaju <asuraparaju at gmail dot com >
5
 *
6
 * This file is part of FFmpeg.
7
 *
8
 * FFmpeg is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * FFmpeg is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with FFmpeg; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 */
22

    
23
/**
24
* @file libavcodec/libdiracdec.c
25
* Dirac decoder support via libdirac library; more details about the Dirac
26
* project can be found at http://dirac.sourceforge.net/.
27
* The libdirac_decoder library implements Dirac specification version 2.2
28
* (http://dirac.sourceforge.net/specification.html).
29
*/
30

    
31
#include "libdirac.h"
32

    
33
#undef NDEBUG
34
#include <assert.h>
35

    
36
#include <libdirac_decoder/dirac_parser.h>
37

    
38
/** contains a single frame returned from Dirac */
39
typedef struct FfmpegDiracDecoderParams {
40
    /** decoder handle */
41
    dirac_decoder_t* p_decoder;
42

    
43
    /** buffer to hold decoded frame */
44
    unsigned char* p_out_frame_buf;
45
} FfmpegDiracDecoderParams;
46

    
47

    
48
/**
49
* returns FFmpeg chroma format
50
*/
51
static enum PixelFormat GetFfmpegChromaFormat(dirac_chroma_t dirac_pix_fmt)
52
{
53
    int num_formats = sizeof(ffmpeg_dirac_pixel_format_map) /
54
                      sizeof(ffmpeg_dirac_pixel_format_map[0]);
55
    int idx;
56

    
57
    for (idx = 0; idx < num_formats; ++idx)
58
        if (ffmpeg_dirac_pixel_format_map[idx].dirac_pix_fmt == dirac_pix_fmt)
59
            return ffmpeg_dirac_pixel_format_map[idx].ff_pix_fmt;
60
    return PIX_FMT_NONE;
61
}
62

    
63
static av_cold int libdirac_decode_init(AVCodecContext *avccontext)
64
{
65

    
66
    FfmpegDiracDecoderParams *p_dirac_params = avccontext->priv_data;
67
    p_dirac_params->p_decoder =  dirac_decoder_init(avccontext->debug);
68

    
69
    if (!p_dirac_params->p_decoder)
70
        return -1;
71

    
72
    return 0;
73
}
74

    
75
static int libdirac_decode_frame(AVCodecContext *avccontext,
76
                                 void *data, int *data_size,
77
                                 AVPacket *avpkt)
78
{
79
    const uint8_t *buf = avpkt->data;
80
    int buf_size = avpkt->size;
81

    
82
    FfmpegDiracDecoderParams *p_dirac_params = avccontext->priv_data;
83
    AVPicture *picture = data;
84
    AVPicture pic;
85
    int pict_size;
86
    unsigned char *buffer[3];
87

    
88
    *data_size = 0;
89

    
90
    if (buf_size > 0) {
91
        /* set data to decode into buffer */
92
        dirac_buffer(p_dirac_params->p_decoder, buf, buf + buf_size);
93
        if ((buf[4] & 0x08) == 0x08 && (buf[4] & 0x03))
94
            avccontext->has_b_frames = 1;
95
    }
96
    while (1) {
97
         /* parse data and process result */
98
        DecoderState state = dirac_parse(p_dirac_params->p_decoder);
99
        switch (state) {
100
        case STATE_BUFFER:
101
            return buf_size;
102

    
103
        case STATE_SEQUENCE:
104
        {
105
            /* tell FFmpeg about sequence details */
106
            dirac_sourceparams_t *src_params = &p_dirac_params->p_decoder->src_params;
107

    
108
            if (avcodec_check_dimensions(avccontext, src_params->width,
109
                                         src_params->height) < 0) {
110
                av_log(avccontext, AV_LOG_ERROR, "Invalid dimensions (%dx%d)\n",
111
                       src_params->width, src_params->height);
112
                avccontext->height = avccontext->width = 0;
113
                return -1;
114
            }
115

    
116
            avccontext->height = src_params->height;
117
            avccontext->width  = src_params->width;
118

    
119
            avccontext->pix_fmt = GetFfmpegChromaFormat(src_params->chroma);
120
            if (avccontext->pix_fmt == PIX_FMT_NONE) {
121
                av_log(avccontext, AV_LOG_ERROR,
122
                       "Dirac chroma format %d not supported currently\n",
123
                       src_params->chroma);
124
                return -1;
125
            }
126

    
127
            avccontext->time_base.den = src_params->frame_rate.numerator;
128
            avccontext->time_base.num = src_params->frame_rate.denominator;
129

    
130
            /* calculate output dimensions */
131
            avpicture_fill(&pic, NULL, avccontext->pix_fmt,
132
                           avccontext->width, avccontext->height);
133

    
134
            pict_size = avpicture_get_size(avccontext->pix_fmt,
135
                                           avccontext->width,
136
                                           avccontext->height);
137

    
138
            /* allocate output buffer */
139
            if (!p_dirac_params->p_out_frame_buf)
140
                p_dirac_params->p_out_frame_buf = av_malloc(pict_size);
141
            buffer[0] = p_dirac_params->p_out_frame_buf;
142
            buffer[1] = p_dirac_params->p_out_frame_buf +
143
                        pic.linesize[0] * avccontext->height;
144
            buffer[2] = buffer[1] +
145
                        pic.linesize[1] * src_params->chroma_height;
146

    
147
            /* tell Dirac about output destination */
148
            dirac_set_buf(p_dirac_params->p_decoder, buffer, NULL);
149
            break;
150
        }
151
        case STATE_SEQUENCE_END:
152
            break;
153

    
154
        case STATE_PICTURE_AVAIL:
155
            /* fill picture with current buffer data from Dirac */
156
            avpicture_fill(picture, p_dirac_params->p_out_frame_buf,
157
                           avccontext->pix_fmt,
158
                           avccontext->width, avccontext->height);
159
            *data_size = sizeof(AVPicture);
160
            return buf_size;
161

    
162
        case STATE_INVALID:
163
            return -1;
164

    
165
        default:
166
            break;
167
        }
168
    }
169

    
170
    return buf_size;
171
}
172

    
173

    
174
static av_cold int libdirac_decode_close(AVCodecContext *avccontext)
175
{
176
    FfmpegDiracDecoderParams *p_dirac_params = avccontext->priv_data;
177
    dirac_decoder_close(p_dirac_params->p_decoder);
178

    
179
    av_freep(&p_dirac_params->p_out_frame_buf);
180

    
181
    return 0;
182
}
183

    
184
static void libdirac_flush(AVCodecContext *avccontext)
185
{
186
    /* Got a seek request. We will need free memory held in the private
187
     * context and free the current Dirac decoder handle and then open
188
     * a new decoder handle. */
189
    libdirac_decode_close(avccontext);
190
    libdirac_decode_init(avccontext);
191
    return;
192
}
193

    
194

    
195

    
196
AVCodec libdirac_decoder = {
197
    "libdirac",
198
    AVMEDIA_TYPE_VIDEO,
199
    CODEC_ID_DIRAC,
200
    sizeof(FfmpegDiracDecoderParams),
201
    libdirac_decode_init,
202
    NULL,
203
    libdirac_decode_close,
204
    libdirac_decode_frame,
205
    CODEC_CAP_DELAY,
206
    .flush = libdirac_flush,
207
    .long_name = NULL_IF_CONFIG_SMALL("libdirac Dirac 2.2"),
208
};