00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00028 #include "internal.h"
00029 #include "mjpeg.h"
00030 #include "mjpegdec.h"
00031
00032 typedef struct MXpegDecodeContext {
00033 MJpegDecodeContext jpg;
00034 AVFrame picture[2];
00035 int picture_index;
00036 int got_sof_data;
00037 int got_mxm_bitmask;
00038 uint8_t *mxm_bitmask;
00039 unsigned bitmask_size;
00040 int has_complete_frame;
00041 uint8_t *completion_bitmask;
00042 unsigned mb_width, mb_height;
00043 } MXpegDecodeContext;
00044
00045 static av_cold int mxpeg_decode_init(AVCodecContext *avctx)
00046 {
00047 MXpegDecodeContext *s = avctx->priv_data;
00048
00049 s->picture[0].reference = s->picture[1].reference = 3;
00050 s->jpg.picture_ptr = &s->picture[0];
00051 return ff_mjpeg_decode_init(avctx);
00052 }
00053
00054 static int mxpeg_decode_app(MXpegDecodeContext *s,
00055 const uint8_t *buf_ptr, int buf_size)
00056 {
00057 int len;
00058 if (buf_size < 2)
00059 return 0;
00060 len = AV_RB16(buf_ptr);
00061 skip_bits(&s->jpg.gb, 8*FFMIN(len,buf_size));
00062
00063 return 0;
00064 }
00065
00066 static int mxpeg_decode_mxm(MXpegDecodeContext *s,
00067 const uint8_t *buf_ptr, int buf_size)
00068 {
00069 unsigned bitmask_size, mb_count;
00070 int i;
00071
00072 s->mb_width = AV_RL16(buf_ptr+4);
00073 s->mb_height = AV_RL16(buf_ptr+6);
00074 mb_count = s->mb_width * s->mb_height;
00075
00076 bitmask_size = (mb_count + 7) >> 3;
00077 if (bitmask_size > buf_size - 12) {
00078 av_log(s->jpg.avctx, AV_LOG_ERROR,
00079 "MXM bitmask is not complete\n");
00080 return AVERROR(EINVAL);
00081 }
00082
00083 if (s->bitmask_size != bitmask_size) {
00084 s->bitmask_size = 0;
00085 av_freep(&s->mxm_bitmask);
00086 s->mxm_bitmask = av_malloc(bitmask_size);
00087 if (!s->mxm_bitmask) {
00088 av_log(s->jpg.avctx, AV_LOG_ERROR,
00089 "MXM bitmask memory allocation error\n");
00090 return AVERROR(ENOMEM);
00091 }
00092
00093 av_freep(&s->completion_bitmask);
00094 s->completion_bitmask = av_mallocz(bitmask_size);
00095 if (!s->completion_bitmask) {
00096 av_log(s->jpg.avctx, AV_LOG_ERROR,
00097 "Completion bitmask memory allocation error\n");
00098 return AVERROR(ENOMEM);
00099 }
00100
00101 s->bitmask_size = bitmask_size;
00102 }
00103
00104 memcpy(s->mxm_bitmask, buf_ptr + 12, bitmask_size);
00105 s->got_mxm_bitmask = 1;
00106
00107 if (!s->has_complete_frame) {
00108 uint8_t completion_check = 0xFF;
00109 for (i = 0; i < bitmask_size; ++i) {
00110 s->completion_bitmask[i] |= s->mxm_bitmask[i];
00111 completion_check &= s->completion_bitmask[i];
00112 }
00113 s->has_complete_frame = !(completion_check ^ 0xFF);
00114 }
00115
00116 return 0;
00117 }
00118
00119 static int mxpeg_decode_com(MXpegDecodeContext *s,
00120 const uint8_t *buf_ptr, int buf_size)
00121 {
00122 int len, ret = 0;
00123 if (buf_size < 2)
00124 return 0;
00125 len = AV_RB16(buf_ptr);
00126 if (len > 14 && len <= buf_size && !strncmp(buf_ptr + 2, "MXM", 3)) {
00127 ret = mxpeg_decode_mxm(s, buf_ptr + 2, len - 2);
00128 }
00129 skip_bits(&s->jpg.gb, 8*FFMIN(len,buf_size));
00130
00131 return ret;
00132 }
00133
00134 static int mxpeg_check_dimensions(MXpegDecodeContext *s, MJpegDecodeContext *jpg,
00135 AVFrame *reference_ptr)
00136 {
00137 if ((jpg->width + 0x0F)>>4 != s->mb_width ||
00138 (jpg->height + 0x0F)>>4 != s->mb_height) {
00139 av_log(jpg->avctx, AV_LOG_ERROR,
00140 "Picture dimensions stored in SOF and MXM mismatch\n");
00141 return AVERROR(EINVAL);
00142 }
00143
00144 if (reference_ptr->data[0]) {
00145 int i;
00146 for (i = 0; i < MAX_COMPONENTS; ++i) {
00147 if ( (!reference_ptr->data[i] ^ !jpg->picture_ptr->data[i]) ||
00148 reference_ptr->linesize[i] != jpg->picture_ptr->linesize[i]) {
00149 av_log(jpg->avctx, AV_LOG_ERROR,
00150 "Dimensions of current and reference picture mismatch\n");
00151 return AVERROR(EINVAL);
00152 }
00153 }
00154 }
00155
00156 return 0;
00157 }
00158
00159 static int mxpeg_decode_frame(AVCodecContext *avctx,
00160 void *data, int *got_frame,
00161 AVPacket *avpkt)
00162 {
00163 const uint8_t *buf = avpkt->data;
00164 int buf_size = avpkt->size;
00165 MXpegDecodeContext *s = avctx->priv_data;
00166 MJpegDecodeContext *jpg = &s->jpg;
00167 const uint8_t *buf_end, *buf_ptr;
00168 const uint8_t *unescaped_buf_ptr;
00169 int unescaped_buf_size;
00170 int start_code;
00171 AVFrame *picture = data;
00172 int ret;
00173
00174 buf_ptr = buf;
00175 buf_end = buf + buf_size;
00176 jpg->got_picture = 0;
00177 s->got_mxm_bitmask = 0;
00178 while (buf_ptr < buf_end) {
00179 start_code = ff_mjpeg_find_marker(jpg, &buf_ptr, buf_end,
00180 &unescaped_buf_ptr, &unescaped_buf_size);
00181 if (start_code < 0)
00182 goto the_end;
00183 {
00184 init_get_bits(&jpg->gb, unescaped_buf_ptr, unescaped_buf_size*8);
00185
00186 if (start_code >= APP0 && start_code <= APP15) {
00187 mxpeg_decode_app(s, unescaped_buf_ptr, unescaped_buf_size);
00188 }
00189
00190 switch (start_code) {
00191 case SOI:
00192 if (jpg->got_picture)
00193 goto the_end;
00194 break;
00195 case EOI:
00196 goto the_end;
00197 case DQT:
00198 ret = ff_mjpeg_decode_dqt(jpg);
00199 if (ret < 0) {
00200 av_log(avctx, AV_LOG_ERROR,
00201 "quantization table decode error\n");
00202 return ret;
00203 }
00204 break;
00205 case DHT:
00206 ret = ff_mjpeg_decode_dht(jpg);
00207 if (ret < 0) {
00208 av_log(avctx, AV_LOG_ERROR,
00209 "huffman table decode error\n");
00210 return ret;
00211 }
00212 break;
00213 case COM:
00214 ret = mxpeg_decode_com(s, unescaped_buf_ptr,
00215 unescaped_buf_size);
00216 if (ret < 0)
00217 return ret;
00218 break;
00219 case SOF0:
00220 s->got_sof_data = 0;
00221 ret = ff_mjpeg_decode_sof(jpg);
00222 if (ret < 0) {
00223 av_log(avctx, AV_LOG_ERROR,
00224 "SOF data decode error\n");
00225 return ret;
00226 }
00227 if (jpg->interlaced) {
00228 av_log(avctx, AV_LOG_ERROR,
00229 "Interlaced mode not supported in MxPEG\n");
00230 return AVERROR(EINVAL);
00231 }
00232 s->got_sof_data = 1;
00233 break;
00234 case SOS:
00235 if (!s->got_sof_data) {
00236 av_log(avctx, AV_LOG_WARNING,
00237 "Can not process SOS without SOF data, skipping\n");
00238 break;
00239 }
00240 if (!jpg->got_picture) {
00241 if (jpg->first_picture) {
00242 av_log(avctx, AV_LOG_WARNING,
00243 "First picture has no SOF, skipping\n");
00244 break;
00245 }
00246 if (!s->got_mxm_bitmask){
00247 av_log(avctx, AV_LOG_WARNING,
00248 "Non-key frame has no MXM, skipping\n");
00249 break;
00250 }
00251
00252 if (jpg->picture_ptr->data[0])
00253 avctx->release_buffer(avctx, jpg->picture_ptr);
00254 if (ff_get_buffer(avctx, jpg->picture_ptr) < 0) {
00255 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00256 return AVERROR(ENOMEM);
00257 }
00258 jpg->picture_ptr->pict_type = AV_PICTURE_TYPE_P;
00259 jpg->picture_ptr->key_frame = 0;
00260 jpg->got_picture = 1;
00261 } else {
00262 jpg->picture_ptr->pict_type = AV_PICTURE_TYPE_I;
00263 jpg->picture_ptr->key_frame = 1;
00264 }
00265
00266 if (s->got_mxm_bitmask) {
00267 AVFrame *reference_ptr = &s->picture[s->picture_index ^ 1];
00268 if (mxpeg_check_dimensions(s, jpg, reference_ptr) < 0)
00269 break;
00270
00271
00272 if (!reference_ptr->data[0] &&
00273 ff_get_buffer(avctx, reference_ptr) < 0) {
00274 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00275 return AVERROR(ENOMEM);
00276 }
00277
00278 ret = ff_mjpeg_decode_sos(jpg, s->mxm_bitmask, reference_ptr);
00279 if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE))
00280 return ret;
00281 } else {
00282 ret = ff_mjpeg_decode_sos(jpg, NULL, NULL);
00283 if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE))
00284 return ret;
00285 }
00286
00287 break;
00288 }
00289
00290 buf_ptr += (get_bits_count(&jpg->gb)+7) >> 3;
00291 }
00292
00293 }
00294
00295 the_end:
00296 if (jpg->got_picture) {
00297 *got_frame = 1;
00298 *picture = *jpg->picture_ptr;
00299 s->picture_index ^= 1;
00300 jpg->picture_ptr = &s->picture[s->picture_index];
00301
00302 if (!s->has_complete_frame) {
00303 if (!s->got_mxm_bitmask)
00304 s->has_complete_frame = 1;
00305 else
00306 *got_frame = 0;
00307 }
00308 }
00309
00310 return buf_ptr - buf;
00311 }
00312
00313 static av_cold int mxpeg_decode_end(AVCodecContext *avctx)
00314 {
00315 MXpegDecodeContext *s = avctx->priv_data;
00316 MJpegDecodeContext *jpg = &s->jpg;
00317 int i;
00318
00319 jpg->picture_ptr = NULL;
00320 ff_mjpeg_decode_end(avctx);
00321
00322 for (i = 0; i < 2; ++i) {
00323 if (s->picture[i].data[0])
00324 avctx->release_buffer(avctx, &s->picture[i]);
00325 }
00326
00327 av_freep(&s->mxm_bitmask);
00328 av_freep(&s->completion_bitmask);
00329
00330 return 0;
00331 }
00332
00333 AVCodec ff_mxpeg_decoder = {
00334 .name = "mxpeg",
00335 .long_name = NULL_IF_CONFIG_SMALL("Mobotix MxPEG video"),
00336 .type = AVMEDIA_TYPE_VIDEO,
00337 .id = AV_CODEC_ID_MXPEG,
00338 .priv_data_size = sizeof(MXpegDecodeContext),
00339 .init = mxpeg_decode_init,
00340 .close = mxpeg_decode_end,
00341 .decode = mxpeg_decode_frame,
00342 .capabilities = CODEC_CAP_DR1,
00343 .max_lowres = 3,
00344 };