* MxPEG decoder
*/
+#include "internal.h"
#include "mjpeg.h"
#include "mjpegdec.h"
typedef struct MXpegDecodeContext {
MJpegDecodeContext jpg;
- AVFrame picture[2]; /* pictures array */
+ AVFrame *picture[2]; /* pictures array */
int picture_index; /* index of current picture */
int got_sof_data; /* true if SOF data successfully parsed */
int got_mxm_bitmask; /* true if MXM bitmask available */
unsigned mb_width, mb_height; /* size of picture in MB's from MXM header */
} MXpegDecodeContext;
+static av_cold int mxpeg_decode_end(AVCodecContext *avctx)
+{
+ MXpegDecodeContext *s = avctx->priv_data;
+ MJpegDecodeContext *jpg = &s->jpg;
+ int i;
+
+ jpg->picture_ptr = NULL;
+ ff_mjpeg_decode_end(avctx);
+
+ for (i = 0; i < 2; ++i)
+ av_frame_free(&s->picture[i]);
+
+ av_freep(&s->mxm_bitmask);
+ av_freep(&s->completion_bitmask);
+
+ return 0;
+}
+
static av_cold int mxpeg_decode_init(AVCodecContext *avctx)
{
MXpegDecodeContext *s = avctx->priv_data;
- s->picture[0].reference = s->picture[1].reference = 3;
- s->jpg.picture_ptr = &s->picture[0];
+ s->picture[0] = av_frame_alloc();
+ s->picture[1] = av_frame_alloc();
+ if (!s->picture[0] || !s->picture[1]) {
+ mxpeg_decode_end(avctx);
+ return AVERROR(ENOMEM);
+ }
+
+ s->jpg.picture_ptr = s->picture[0];
return ff_mjpeg_decode_init(avctx);
}
}
static int mxpeg_decode_frame(AVCodecContext *avctx,
- void *data, int *data_size,
+ void *data, int *got_frame,
AVPacket *avpkt)
{
const uint8_t *buf = avpkt->data;
const uint8_t *unescaped_buf_ptr;
int unescaped_buf_size;
int start_code;
- AVFrame *picture = data;
int ret;
buf_ptr = buf;
break;
}
/* use stored SOF data to allocate current picture */
- if (jpg->picture_ptr->data[0])
- avctx->release_buffer(avctx, jpg->picture_ptr);
- if (avctx->get_buffer(avctx, jpg->picture_ptr) < 0) {
+ av_frame_unref(jpg->picture_ptr);
+ if (ff_get_buffer(avctx, jpg->picture_ptr,
+ AV_GET_BUFFER_FLAG_REF) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return AVERROR(ENOMEM);
}
}
if (s->got_mxm_bitmask) {
- AVFrame *reference_ptr = &s->picture[s->picture_index ^ 1];
+ AVFrame *reference_ptr = s->picture[s->picture_index ^ 1];
if (mxpeg_check_dimensions(s, jpg, reference_ptr) < 0)
break;
/* allocate dummy reference picture if needed */
if (!reference_ptr->data[0] &&
- avctx->get_buffer(avctx, reference_ptr) < 0) {
+ ff_get_buffer(avctx, reference_ptr,
+ AV_GET_BUFFER_FLAG_REF) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return AVERROR(ENOMEM);
}
the_end:
if (jpg->got_picture) {
- *data_size = sizeof(AVFrame);
- *picture = *jpg->picture_ptr;
+ int ret = av_frame_ref(data, jpg->picture_ptr);
+ if (ret < 0)
+ return ret;
+ *got_frame = 1;
+
s->picture_index ^= 1;
- jpg->picture_ptr = &s->picture[s->picture_index];
+ jpg->picture_ptr = s->picture[s->picture_index];
if (!s->has_complete_frame) {
if (!s->got_mxm_bitmask)
s->has_complete_frame = 1;
else
- *data_size = 0;
+ *got_frame = 0;
}
}
return buf_ptr - buf;
}
-static av_cold int mxpeg_decode_end(AVCodecContext *avctx)
-{
- MXpegDecodeContext *s = avctx->priv_data;
- MJpegDecodeContext *jpg = &s->jpg;
- int i;
-
- jpg->picture_ptr = NULL;
- ff_mjpeg_decode_end(avctx);
-
- for (i = 0; i < 2; ++i) {
- if (s->picture[i].data[0])
- avctx->release_buffer(avctx, &s->picture[i]);
- }
-
- av_freep(&s->mxm_bitmask);
- av_freep(&s->completion_bitmask);
-
- return 0;
-}
-
AVCodec ff_mxpeg_decoder = {
.name = "mxpeg",
.long_name = NULL_IF_CONFIG_SMALL("Mobotix MxPEG video"),
.type = AVMEDIA_TYPE_VIDEO,
- .id = CODEC_ID_MXPEG,
+ .id = AV_CODEC_ID_MXPEG,
.priv_data_size = sizeof(MXpegDecodeContext),
.init = mxpeg_decode_init,
.close = mxpeg_decode_end,
.decode = mxpeg_decode_frame,
.capabilities = CODEC_CAP_DR1,
- .max_lowres = 3,
};