1/*
2 * Dirac decoder support via Schroedinger libraries
3 * Copyright (c) 2008 BBC, Anuradha Suraparaju <asuraparaju at gmail dot com >
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22/**
23* @file
24* Dirac decoder support via libschroedinger-1.0 libraries. More details about
25* the Schroedinger project can be found at http://www.diracvideo.org/.
26* The library implements Dirac Specification Version 2.2.
27* (http://dirac.sourceforge.net/specification.html).
28*/
29
30#include "avcodec.h"
31#include "libdirac_libschro.h"
32#include "libschroedinger.h"
33
34#undef NDEBUG
35#include <assert.h>
36
37
38#include <schroedinger/schro.h>
39#include <schroedinger/schrodebug.h>
40#include <schroedinger/schrovideoformat.h>
41
42/** libschroedinger decoder private data */
43typedef struct FfmpegSchroDecoderParams {
44    /** Schroedinger video format */
45    SchroVideoFormat *format;
46
47    /** Schroedinger frame format */
48    SchroFrameFormat frame_format;
49
50    /** decoder handle */
51    SchroDecoder* decoder;
52
53    /** queue storing decoded frames */
54    FfmpegDiracSchroQueue dec_frame_queue;
55
56    /** end of sequence signalled */
57    int eos_signalled;
58
59    /** end of sequence pulled */
60    int eos_pulled;
61
62    /** decoded picture */
63    AVPicture dec_pic;
64} FfmpegSchroDecoderParams;
65
66typedef struct FfmpegSchroParseUnitContext {
67    const uint8_t *buf;
68    int           buf_size;
69} FfmpegSchroParseUnitContext;
70
71
72static void libschroedinger_decode_buffer_free(SchroBuffer *schro_buf,
73                                               void *priv);
74
75static void FfmpegSchroParseContextInit(FfmpegSchroParseUnitContext *parse_ctx,
76                                        const uint8_t *buf, int buf_size)
77{
78    parse_ctx->buf           = buf;
79    parse_ctx->buf_size      = buf_size;
80}
81
82static SchroBuffer* FfmpegFindNextSchroParseUnit(FfmpegSchroParseUnitContext *parse_ctx)
83{
84    SchroBuffer *enc_buf = NULL;
85    int next_pu_offset = 0;
86    unsigned char *in_buf;
87
88    if (parse_ctx->buf_size < 13 ||
89        parse_ctx->buf[0] != 'B' ||
90        parse_ctx->buf[1] != 'B' ||
91        parse_ctx->buf[2] != 'C' ||
92        parse_ctx->buf[3] != 'D')
93        return NULL;
94
95    next_pu_offset = (parse_ctx->buf[5] << 24) +
96                     (parse_ctx->buf[6] << 16) +
97                     (parse_ctx->buf[7] <<  8) +
98                      parse_ctx->buf[8];
99
100    if (next_pu_offset == 0 &&
101        SCHRO_PARSE_CODE_IS_END_OF_SEQUENCE(parse_ctx->buf[4]))
102        next_pu_offset = 13;
103
104    if (next_pu_offset <= 0 || parse_ctx->buf_size < next_pu_offset)
105        return NULL;
106
107    in_buf = av_malloc(next_pu_offset);
108    memcpy(in_buf, parse_ctx->buf, next_pu_offset);
109    enc_buf       = schro_buffer_new_with_data(in_buf, next_pu_offset);
110    enc_buf->free = libschroedinger_decode_buffer_free;
111    enc_buf->priv = in_buf;
112
113    parse_ctx->buf      += next_pu_offset;
114    parse_ctx->buf_size -= next_pu_offset;
115
116    return enc_buf;
117}
118
119/**
120* Returns FFmpeg chroma format.
121*/
122static enum PixelFormat GetFfmpegChromaFormat(SchroChromaFormat schro_pix_fmt)
123{
124    int num_formats = sizeof(ffmpeg_schro_pixel_format_map) /
125                      sizeof(ffmpeg_schro_pixel_format_map[0]);
126    int idx;
127
128    for (idx = 0; idx < num_formats; ++idx)
129        if (ffmpeg_schro_pixel_format_map[idx].schro_pix_fmt == schro_pix_fmt)
130            return ffmpeg_schro_pixel_format_map[idx].ff_pix_fmt;
131    return PIX_FMT_NONE;
132}
133
134static av_cold int libschroedinger_decode_init(AVCodecContext *avccontext)
135{
136
137    FfmpegSchroDecoderParams *p_schro_params = avccontext->priv_data;
138    /* First of all, initialize our supporting libraries. */
139    schro_init();
140
141    schro_debug_set_level(avccontext->debug);
142    p_schro_params->decoder = schro_decoder_new();
143    schro_decoder_set_skip_ratio(p_schro_params->decoder, 1);
144
145    if (!p_schro_params->decoder)
146        return -1;
147
148    /* Initialize the decoded frame queue. */
149    ff_dirac_schro_queue_init(&p_schro_params->dec_frame_queue);
150    return 0;
151}
152
153static void libschroedinger_decode_buffer_free(SchroBuffer *schro_buf,
154                                               void *priv)
155{
156    av_freep(&priv);
157}
158
159static void libschroedinger_decode_frame_free(void *frame)
160{
161    schro_frame_unref(frame);
162}
163
164static void libschroedinger_handle_first_access_unit(AVCodecContext *avccontext)
165{
166    FfmpegSchroDecoderParams *p_schro_params = avccontext->priv_data;
167    SchroDecoder *decoder = p_schro_params->decoder;
168
169    p_schro_params->format = schro_decoder_get_video_format(decoder);
170
171    /* Tell FFmpeg about sequence details. */
172    if (avcodec_check_dimensions(avccontext, p_schro_params->format->width,
173                                 p_schro_params->format->height) < 0) {
174        av_log(avccontext, AV_LOG_ERROR, "invalid dimensions (%dx%d)\n",
175               p_schro_params->format->width, p_schro_params->format->height);
176        avccontext->height = avccontext->width = 0;
177        return;
178    }
179    avccontext->height  = p_schro_params->format->height;
180    avccontext->width   = p_schro_params->format->width;
181    avccontext->pix_fmt = GetFfmpegChromaFormat(p_schro_params->format->chroma_format);
182
183    if (ff_get_schro_frame_format(p_schro_params->format->chroma_format,
184                                  &p_schro_params->frame_format) == -1) {
185        av_log(avccontext, AV_LOG_ERROR,
186               "This codec currently only supports planar YUV 4:2:0, 4:2:2 "
187               "and 4:4:4 formats.\n");
188        return;
189    }
190
191    avccontext->time_base.den = p_schro_params->format->frame_rate_numerator;
192    avccontext->time_base.num = p_schro_params->format->frame_rate_denominator;
193
194    if (!p_schro_params->dec_pic.data[0])
195        avpicture_alloc(&p_schro_params->dec_pic,
196                        avccontext->pix_fmt,
197                        avccontext->width,
198                        avccontext->height);
199}
200
201static int libschroedinger_decode_frame(AVCodecContext *avccontext,
202                                        void *data, int *data_size,
203                                        AVPacket *avpkt)
204{
205    const uint8_t *buf = avpkt->data;
206    int buf_size = avpkt->size;
207
208    FfmpegSchroDecoderParams *p_schro_params = avccontext->priv_data;
209    SchroDecoder *decoder = p_schro_params->decoder;
210    SchroVideoFormat *format;
211    AVPicture *picture = data;
212    SchroBuffer *enc_buf;
213    SchroFrame* frame;
214    int state;
215    int go = 1;
216    int outer = 1;
217    FfmpegSchroParseUnitContext parse_ctx;
218
219    *data_size = 0;
220
221    FfmpegSchroParseContextInit(&parse_ctx, buf, buf_size);
222    if (!buf_size) {
223        if (!p_schro_params->eos_signalled) {
224            state = schro_decoder_push_end_of_stream(decoder);
225            p_schro_params->eos_signalled = 1;
226        }
227    }
228
229    /* Loop through all the individual parse units in the input buffer */
230    do {
231        if ((enc_buf = FfmpegFindNextSchroParseUnit(&parse_ctx))) {
232            /* Push buffer into decoder. */
233            if (SCHRO_PARSE_CODE_IS_PICTURE(enc_buf->data[4]) &&
234                SCHRO_PARSE_CODE_NUM_REFS(enc_buf->data[4]) > 0)
235                avccontext->has_b_frames = 1;
236            state = schro_decoder_push(decoder, enc_buf);
237            if (state == SCHRO_DECODER_FIRST_ACCESS_UNIT)
238                libschroedinger_handle_first_access_unit(avccontext);
239            go = 1;
240        } else
241            outer = 0;
242        format = p_schro_params->format;
243
244        while (go) {
245            /* Parse data and process result. */
246            state = schro_decoder_wait(decoder);
247            switch (state) {
248            case SCHRO_DECODER_FIRST_ACCESS_UNIT:
249                libschroedinger_handle_first_access_unit(avccontext);
250                break;
251
252            case SCHRO_DECODER_NEED_BITS:
253                /* Need more input data - stop iterating over what we have. */
254                go = 0;
255                break;
256
257            case SCHRO_DECODER_NEED_FRAME:
258                /* Decoder needs a frame - create one and push it in. */
259                frame = ff_create_schro_frame(avccontext,
260                                              p_schro_params->frame_format);
261                schro_decoder_add_output_picture(decoder, frame);
262                break;
263
264            case SCHRO_DECODER_OK:
265                /* Pull a frame out of the decoder. */
266                frame = schro_decoder_pull(decoder);
267
268                if (frame)
269                    ff_dirac_schro_queue_push_back(&p_schro_params->dec_frame_queue,
270                                                   frame);
271                break;
272            case SCHRO_DECODER_EOS:
273                go = 0;
274                p_schro_params->eos_pulled = 1;
275                schro_decoder_reset(decoder);
276                outer = 0;
277                break;
278
279            case SCHRO_DECODER_ERROR:
280                return -1;
281                break;
282            }
283        }
284    } while (outer);
285
286    /* Grab next frame to be returned from the top of the queue. */
287    frame = ff_dirac_schro_queue_pop(&p_schro_params->dec_frame_queue);
288
289    if (frame) {
290        memcpy(p_schro_params->dec_pic.data[0],
291               frame->components[0].data,
292               frame->components[0].length);
293
294        memcpy(p_schro_params->dec_pic.data[1],
295               frame->components[1].data,
296               frame->components[1].length);
297
298        memcpy(p_schro_params->dec_pic.data[2],
299               frame->components[2].data,
300               frame->components[2].length);
301
302        /* Fill picture with current buffer data from Schroedinger. */
303        avpicture_fill(picture, p_schro_params->dec_pic.data[0],
304                       avccontext->pix_fmt,
305                       avccontext->width, avccontext->height);
306
307        *data_size = sizeof(AVPicture);
308
309        /* Now free the frame resources. */
310        libschroedinger_decode_frame_free(frame);
311    }
312    return buf_size;
313}
314
315
316static av_cold int libschroedinger_decode_close(AVCodecContext *avccontext)
317{
318    FfmpegSchroDecoderParams *p_schro_params = avccontext->priv_data;
319    /* Free the decoder. */
320    schro_decoder_free(p_schro_params->decoder);
321    av_freep(&p_schro_params->format);
322
323    avpicture_free(&p_schro_params->dec_pic);
324
325    /* Free data in the output frame queue. */
326    ff_dirac_schro_queue_free(&p_schro_params->dec_frame_queue,
327                              libschroedinger_decode_frame_free);
328
329    return 0;
330}
331
332static void libschroedinger_flush(AVCodecContext *avccontext)
333{
334    /* Got a seek request. Free the decoded frames queue and then reset
335     * the decoder */
336    FfmpegSchroDecoderParams *p_schro_params = avccontext->priv_data;
337
338    /* Free data in the output frame queue. */
339    ff_dirac_schro_queue_free(&p_schro_params->dec_frame_queue,
340                              libschroedinger_decode_frame_free);
341
342    ff_dirac_schro_queue_init(&p_schro_params->dec_frame_queue);
343    schro_decoder_reset(p_schro_params->decoder);
344    p_schro_params->eos_pulled = 0;
345    p_schro_params->eos_signalled = 0;
346}
347
348AVCodec libschroedinger_decoder = {
349    "libschroedinger",
350    AVMEDIA_TYPE_VIDEO,
351    CODEC_ID_DIRAC,
352    sizeof(FfmpegSchroDecoderParams),
353    libschroedinger_decode_init,
354    NULL,
355    libschroedinger_decode_close,
356    libschroedinger_decode_frame,
357    CODEC_CAP_DELAY,
358    .flush = libschroedinger_flush,
359    .long_name = NULL_IF_CONFIG_SMALL("libschroedinger Dirac 2.2"),
360};
361