3 * Copyright (c) 2011 Anatoly Nenashev
5 * This file is part of FFmpeg.
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.
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.
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
32 typedef struct MXpegDecodeContext
{
33 MJpegDecodeContext jpg
;
34 AVFrame
*picture
[2]; /* pictures array */
35 int picture_index
; /* index of current picture */
36 int got_sof_data
; /* true if SOF data successfully parsed */
37 int got_mxm_bitmask
; /* true if MXM bitmask available */
38 uint8_t *mxm_bitmask
; /* bitmask buffer */
39 unsigned bitmask_size
; /* size of bitmask */
40 int has_complete_frame
; /* true if has complete frame */
41 uint8_t *completion_bitmask
; /* completion bitmask of macroblocks */
42 unsigned mb_width
, mb_height
; /* size of picture in MB's from MXM header */
45 static av_cold
int mxpeg_decode_end(AVCodecContext
*avctx
)
47 MXpegDecodeContext
*s
= avctx
->priv_data
;
48 MJpegDecodeContext
*jpg
= &s
->jpg
;
51 jpg
->picture_ptr
= NULL
;
52 ff_mjpeg_decode_end(avctx
);
54 for (i
= 0; i
< 2; ++i
)
55 av_frame_free(&s
->picture
[i
]);
58 av_freep(&s
->mxm_bitmask
);
59 av_freep(&s
->completion_bitmask
);
64 static av_cold
int mxpeg_decode_init(AVCodecContext
*avctx
)
66 MXpegDecodeContext
*s
= avctx
->priv_data
;
68 s
->picture
[0] = av_frame_alloc();
69 s
->picture
[1] = av_frame_alloc();
70 if (!s
->picture
[0] || !s
->picture
[1]) {
71 mxpeg_decode_end(avctx
);
72 return AVERROR(ENOMEM
);
75 s
->jpg
.picture_ptr
= s
->picture
[0];
76 return ff_mjpeg_decode_init(avctx
);
79 static int mxpeg_decode_app(MXpegDecodeContext
*s
,
80 const uint8_t *buf_ptr
, int buf_size
)
85 len
= AV_RB16(buf_ptr
);
86 skip_bits(&s
->jpg
.gb
, 8*FFMIN(len
,buf_size
));
91 static int mxpeg_decode_mxm(MXpegDecodeContext
*s
,
92 const uint8_t *buf_ptr
, int buf_size
)
94 unsigned bitmask_size
, mb_count
;
97 s
->mb_width
= AV_RL16(buf_ptr
+4);
98 s
->mb_height
= AV_RL16(buf_ptr
+6);
99 mb_count
= s
->mb_width
* s
->mb_height
;
101 bitmask_size
= (mb_count
+ 7) >> 3;
102 if (bitmask_size
> buf_size
- 12) {
103 av_log(s
->jpg
.avctx
, AV_LOG_ERROR
,
104 "MXM bitmask is not complete\n");
105 return AVERROR(EINVAL
);
108 if (s
->bitmask_size
!= bitmask_size
) {
110 av_freep(&s
->mxm_bitmask
);
111 s
->mxm_bitmask
= av_malloc(bitmask_size
);
112 if (!s
->mxm_bitmask
) {
113 av_log(s
->jpg
.avctx
, AV_LOG_ERROR
,
114 "MXM bitmask memory allocation error\n");
115 return AVERROR(ENOMEM
);
118 av_freep(&s
->completion_bitmask
);
119 s
->completion_bitmask
= av_mallocz(bitmask_size
);
120 if (!s
->completion_bitmask
) {
121 av_log(s
->jpg
.avctx
, AV_LOG_ERROR
,
122 "Completion bitmask memory allocation error\n");
123 return AVERROR(ENOMEM
);
126 s
->bitmask_size
= bitmask_size
;
129 memcpy(s
->mxm_bitmask
, buf_ptr
+ 12, bitmask_size
);
130 s
->got_mxm_bitmask
= 1;
132 if (!s
->has_complete_frame
) {
133 uint8_t completion_check
= 0xFF;
134 for (i
= 0; i
< bitmask_size
; ++i
) {
135 s
->completion_bitmask
[i
] |= s
->mxm_bitmask
[i
];
136 completion_check
&= s
->completion_bitmask
[i
];
138 s
->has_complete_frame
= !(completion_check
^ 0xFF);
144 static int mxpeg_decode_com(MXpegDecodeContext
*s
,
145 const uint8_t *buf_ptr
, int buf_size
)
150 len
= AV_RB16(buf_ptr
);
151 if (len
> 14 && len
<= buf_size
&& !strncmp(buf_ptr
+ 2, "MXM", 3)) {
152 ret
= mxpeg_decode_mxm(s
, buf_ptr
+ 2, len
- 2);
154 skip_bits(&s
->jpg
.gb
, 8*FFMIN(len
,buf_size
));
159 static int mxpeg_check_dimensions(MXpegDecodeContext
*s
, MJpegDecodeContext
*jpg
,
160 AVFrame
*reference_ptr
)
162 if ((jpg
->width
+ 0x0F)>>4 != s
->mb_width
||
163 (jpg
->height
+ 0x0F)>>4 != s
->mb_height
) {
164 av_log(jpg
->avctx
, AV_LOG_ERROR
,
165 "Picture dimensions stored in SOF and MXM mismatch\n");
166 return AVERROR(EINVAL
);
169 if (reference_ptr
->data
[0]) {
171 for (i
= 0; i
< MAX_COMPONENTS
; ++i
) {
172 if ( (!reference_ptr
->data
[i
] ^ !jpg
->picture_ptr
->data
[i
]) ||
173 reference_ptr
->linesize
[i
] != jpg
->picture_ptr
->linesize
[i
]) {
174 av_log(jpg
->avctx
, AV_LOG_ERROR
,
175 "Dimensions of current and reference picture mismatch\n");
176 return AVERROR(EINVAL
);
184 static int mxpeg_decode_frame(AVCodecContext
*avctx
,
185 void *data
, int *got_frame
,
188 const uint8_t *buf
= avpkt
->data
;
189 int buf_size
= avpkt
->size
;
190 MXpegDecodeContext
*s
= avctx
->priv_data
;
191 MJpegDecodeContext
*jpg
= &s
->jpg
;
192 const uint8_t *buf_end
, *buf_ptr
;
193 const uint8_t *unescaped_buf_ptr
;
194 int unescaped_buf_size
;
199 buf_end
= buf
+ buf_size
;
200 jpg
->got_picture
= 0;
201 s
->got_mxm_bitmask
= 0;
202 while (buf_ptr
< buf_end
) {
203 start_code
= ff_mjpeg_find_marker(jpg
, &buf_ptr
, buf_end
,
204 &unescaped_buf_ptr
, &unescaped_buf_size
);
208 init_get_bits(&jpg
->gb
, unescaped_buf_ptr
, unescaped_buf_size
*8);
210 if (start_code
>= APP0
&& start_code
<= APP15
) {
211 mxpeg_decode_app(s
, unescaped_buf_ptr
, unescaped_buf_size
);
214 switch (start_code
) {
216 if (jpg
->got_picture
) //emulating EOI
222 ret
= ff_mjpeg_decode_dqt(jpg
);
224 av_log(avctx
, AV_LOG_ERROR
,
225 "quantization table decode error\n");
230 ret
= ff_mjpeg_decode_dht(jpg
);
232 av_log(avctx
, AV_LOG_ERROR
,
233 "huffman table decode error\n");
238 ret
= mxpeg_decode_com(s
, unescaped_buf_ptr
,
245 ret
= ff_mjpeg_decode_sof(jpg
);
247 av_log(avctx
, AV_LOG_ERROR
,
248 "SOF data decode error\n");
251 if (jpg
->interlaced
) {
252 av_log(avctx
, AV_LOG_ERROR
,
253 "Interlaced mode not supported in MxPEG\n");
254 return AVERROR(EINVAL
);
259 if (!s
->got_sof_data
) {
260 av_log(avctx
, AV_LOG_WARNING
,
261 "Can not process SOS without SOF data, skipping\n");
264 if (!jpg
->got_picture
) {
265 if (jpg
->first_picture
) {
266 av_log(avctx
, AV_LOG_WARNING
,
267 "First picture has no SOF, skipping\n");
270 if (!s
->got_mxm_bitmask
){
271 av_log(avctx
, AV_LOG_WARNING
,
272 "Non-key frame has no MXM, skipping\n");
275 /* use stored SOF data to allocate current picture */
276 av_frame_unref(jpg
->picture_ptr
);
277 if ((ret
= ff_get_buffer(avctx
, jpg
->picture_ptr
,
278 AV_GET_BUFFER_FLAG_REF
)) < 0)
280 jpg
->picture_ptr
->pict_type
= AV_PICTURE_TYPE_P
;
281 jpg
->picture_ptr
->key_frame
= 0;
282 jpg
->got_picture
= 1;
284 jpg
->picture_ptr
->pict_type
= AV_PICTURE_TYPE_I
;
285 jpg
->picture_ptr
->key_frame
= 1;
288 if (s
->got_mxm_bitmask
) {
289 AVFrame
*reference_ptr
= s
->picture
[s
->picture_index
^ 1];
290 if (mxpeg_check_dimensions(s
, jpg
, reference_ptr
) < 0)
293 /* allocate dummy reference picture if needed */
294 if (!reference_ptr
->data
[0] &&
295 (ret
= ff_get_buffer(avctx
, reference_ptr
,
296 AV_GET_BUFFER_FLAG_REF
)) < 0)
299 ret
= ff_mjpeg_decode_sos(jpg
, s
->mxm_bitmask
, s
->bitmask_size
, reference_ptr
);
300 if (ret
< 0 && (avctx
->err_recognition
& AV_EF_EXPLODE
))
303 ret
= ff_mjpeg_decode_sos(jpg
, NULL
, 0, NULL
);
304 if (ret
< 0 && (avctx
->err_recognition
& AV_EF_EXPLODE
))
311 buf_ptr
+= (get_bits_count(&jpg
->gb
)+7) >> 3;
317 if (jpg
->got_picture
) {
318 int ret
= av_frame_ref(data
, jpg
->picture_ptr
);
323 s
->picture_index
^= 1;
324 jpg
->picture_ptr
= s
->picture
[s
->picture_index
];
326 if (!s
->has_complete_frame
) {
327 if (!s
->got_mxm_bitmask
)
328 s
->has_complete_frame
= 1;
334 return buf_ptr
- buf
;
337 AVCodec ff_mxpeg_decoder
= {
339 .long_name
= NULL_IF_CONFIG_SMALL("Mobotix MxPEG video"),
340 .type
= AVMEDIA_TYPE_VIDEO
,
341 .id
= AV_CODEC_ID_MXPEG
,
342 .priv_data_size
= sizeof(MXpegDecodeContext
),
343 .init
= mxpeg_decode_init
,
344 .close
= mxpeg_decode_end
,
345 .decode
= mxpeg_decode_frame
,
346 .capabilities
= CODEC_CAP_DR1
,