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