Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/*
2
 * Apple MJPEG-B decoder
3
 * Copyright (c) 2002 Alex Beregszaszi
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
 * Apple MJPEG-B decoder.
25
 */
26
 
27
#include "avcodec.h"
28
#include "mjpeg.h"
29
#include "mjpegdec.h"
30
 
31
static uint32_t read_offs(AVCodecContext *avctx, GetBitContext *gb, uint32_t size, const char *err_msg){
32
    uint32_t offs= get_bits_long(gb, 32);
33
    if(offs >= size){
34
        av_log(avctx, AV_LOG_WARNING, err_msg, offs, size);
35
        return 0;
36
    }
37
    return offs;
38
}
39
 
40
static int mjpegb_decode_frame(AVCodecContext *avctx,
41
                              void *data, int *got_frame,
42
                              AVPacket *avpkt)
43
{
44
    const uint8_t *buf = avpkt->data;
45
    int buf_size = avpkt->size;
46
    MJpegDecodeContext *s = avctx->priv_data;
47
    const uint8_t *buf_end, *buf_ptr;
48
    GetBitContext hgb; /* for the header */
49
    uint32_t dqt_offs, dht_offs, sof_offs, sos_offs, second_field_offs;
50
    uint32_t field_size, sod_offs;
51
    int ret;
52
 
53
    buf_ptr = buf;
54
    buf_end = buf + buf_size;
55
    s->got_picture = 0;
56
 
57
read_header:
58
    /* reset on every SOI */
59
    s->restart_interval = 0;
60
    s->restart_count = 0;
61
    s->mjpb_skiptosod = 0;
62
 
63
    if (buf_end - buf_ptr >= 1 << 28)
64
        return AVERROR_INVALIDDATA;
65
 
66
    init_get_bits(&hgb, buf_ptr, /*buf_size*/(buf_end - buf_ptr)*8);
67
 
68
    skip_bits(&hgb, 32); /* reserved zeros */
69
 
70
    if (get_bits_long(&hgb, 32) != MKBETAG('m','j','p','g'))
71
    {
72
        av_log(avctx, AV_LOG_WARNING, "not mjpeg-b (bad fourcc)\n");
73
        return AVERROR_INVALIDDATA;
74
    }
75
 
76
    field_size = get_bits_long(&hgb, 32); /* field size */
77
    av_log(avctx, AV_LOG_DEBUG, "field size: 0x%x\n", field_size);
78
    skip_bits(&hgb, 32); /* padded field size */
79
    second_field_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "second_field_offs is %d and size is %d\n");
80
    av_log(avctx, AV_LOG_DEBUG, "second field offs: 0x%x\n", second_field_offs);
81
 
82
    dqt_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "dqt is %d and size is %d\n");
83
    av_log(avctx, AV_LOG_DEBUG, "dqt offs: 0x%x\n", dqt_offs);
84
    if (dqt_offs)
85
    {
86
        init_get_bits(&s->gb, buf_ptr+dqt_offs, (buf_end - (buf_ptr+dqt_offs))*8);
87
        s->start_code = DQT;
88
        if (ff_mjpeg_decode_dqt(s) < 0 &&
89
            (avctx->err_recognition & AV_EF_EXPLODE))
90
          return AVERROR_INVALIDDATA;
91
    }
92
 
93
    dht_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "dht is %d and size is %d\n");
94
    av_log(avctx, AV_LOG_DEBUG, "dht offs: 0x%x\n", dht_offs);
95
    if (dht_offs)
96
    {
97
        init_get_bits(&s->gb, buf_ptr+dht_offs, (buf_end - (buf_ptr+dht_offs))*8);
98
        s->start_code = DHT;
99
        ff_mjpeg_decode_dht(s);
100
    }
101
 
102
    sof_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "sof is %d and size is %d\n");
103
    av_log(avctx, AV_LOG_DEBUG, "sof offs: 0x%x\n", sof_offs);
104
    if (sof_offs)
105
    {
106
        init_get_bits(&s->gb, buf_ptr+sof_offs, (buf_end - (buf_ptr+sof_offs))*8);
107
        s->start_code = SOF0;
108
        if (ff_mjpeg_decode_sof(s) < 0)
109
            return -1;
110
    }
111
 
112
    sos_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "sos is %d and size is %d\n");
113
    av_log(avctx, AV_LOG_DEBUG, "sos offs: 0x%x\n", sos_offs);
114
    sod_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "sof is %d and size is %d\n");
115
    av_log(avctx, AV_LOG_DEBUG, "sod offs: 0x%x\n", sod_offs);
116
    if (sos_offs)
117
    {
118
        init_get_bits(&s->gb, buf_ptr + sos_offs,
119
                      8 * FFMIN(field_size, buf_end - buf_ptr - sos_offs));
120
        s->mjpb_skiptosod = (sod_offs - sos_offs - show_bits(&s->gb, 16));
121
        s->start_code = SOS;
122
        if (ff_mjpeg_decode_sos(s, NULL, NULL) < 0 &&
123
            (avctx->err_recognition & AV_EF_EXPLODE))
124
          return AVERROR_INVALIDDATA;
125
    }
126
 
127
    if (s->interlaced) {
128
        s->bottom_field ^= 1;
129
        /* if not bottom field, do not output image yet */
130
        if (s->bottom_field != s->interlace_polarity && second_field_offs)
131
        {
132
            buf_ptr = buf + second_field_offs;
133
            goto read_header;
134
            }
135
    }
136
 
137
    //XXX FIXME factorize, this looks very similar to the EOI code
138
 
139
    if(!s->got_picture) {
140
        av_log(avctx, AV_LOG_WARNING, "no picture\n");
141
        return buf_size;
142
    }
143
 
144
    if ((ret = av_frame_ref(data, s->picture_ptr)) < 0)
145
        return ret;
146
    *got_frame = 1;
147
 
148
    if (!s->lossless && avctx->debug & FF_DEBUG_QP) {
149
        av_log(avctx, AV_LOG_DEBUG, "QP: %d\n",
150
               FFMAX3(s->qscale[0], s->qscale[1], s->qscale[2]));
151
    }
152
 
153
    return buf_size;
154
}
155
 
156
AVCodec ff_mjpegb_decoder = {
157
    .name           = "mjpegb",
158
    .long_name      = NULL_IF_CONFIG_SMALL("Apple MJPEG-B"),
159
    .type           = AVMEDIA_TYPE_VIDEO,
160
    .id             = AV_CODEC_ID_MJPEGB,
161
    .priv_data_size = sizeof(MJpegDecodeContext),
162
    .init           = ff_mjpeg_decode_init,
163
    .close          = ff_mjpeg_decode_end,
164
    .decode         = mjpegb_decode_frame,
165
    .capabilities   = CODEC_CAP_DR1,
166
    .max_lowres     = 3,
167
};