mirror of
https://github.com/Motion-Project/motion.git
synced 2026-02-01 18:41:37 -05:00
114 lines
2.9 KiB
C
114 lines
2.9 KiB
C
#include "mjpeg.h"
|
|
#include "motion.h"
|
|
|
|
#ifdef HAVE_FFMPEG
|
|
|
|
/* EXPERIMENTAL : some mutex needs to be set around ! */
|
|
|
|
void MJPEGinit(){
|
|
avcodec_init();
|
|
avcodec_register_all();
|
|
}
|
|
|
|
|
|
struct mjpeg * MJPEGStartDecoder(unsigned int width, unsigned int height){
|
|
|
|
struct mjpeg *MJPEG_ST;
|
|
|
|
MJPEG_ST = mymalloc(sizeof(struct mjpeg));
|
|
memset(MJPEG_ST, 0, sizeof(struct mjpeg));
|
|
|
|
/* Get a mutex lock. */
|
|
pthread_mutex_lock(&global_lock);
|
|
|
|
MJPEGinit();
|
|
|
|
/* Release the lock. */
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
MJPEG_ST->mjpegDecoder = avcodec_find_decoder(CODEC_ID_MJPEG);
|
|
if (!MJPEG_ST->mjpegDecoder){
|
|
motion_log(LOG_ERR,1,"Could not find MJPEG decoder");
|
|
return NULL;
|
|
}
|
|
|
|
MJPEG_ST->mjpegDecContext = avcodec_alloc_context();
|
|
MJPEG_ST->pictureIn = avcodec_alloc_frame();
|
|
|
|
MJPEG_ST->mjpegDecContext->codec_id = CODEC_ID_MJPEG;
|
|
MJPEG_ST->mjpegDecContext->width = width;
|
|
MJPEG_ST->mjpegDecContext->height = height;
|
|
MJPEG_ST->mjpegDecContext->pix_fmt = PIX_FMT_YUV420P;
|
|
|
|
/* Get a mutex lock. */
|
|
pthread_mutex_lock(&global_lock);
|
|
|
|
/* open it */
|
|
if (avcodec_open(MJPEG_ST->mjpegDecContext, MJPEG_ST->mjpegDecoder) < 0){
|
|
motion_log(LOG_ERR,1,"Could not open MJPEG Decoder");
|
|
pthread_mutex_unlock(&global_lock);
|
|
return NULL;
|
|
}
|
|
|
|
/* Release the lock. */
|
|
pthread_mutex_unlock(&global_lock);
|
|
|
|
return MJPEG_ST;
|
|
}
|
|
|
|
|
|
unsigned char * MJPEGDecodeFrame(unsigned char *mjpegFrame, int mjpegFrameLen, unsigned char *outbuf,
|
|
int outbufSize, struct mjpeg *MJPEG_ST){
|
|
int got_picture;
|
|
|
|
memset(outbuf, 0, outbufSize);
|
|
|
|
int len = avcodec_decode_video(MJPEG_ST->mjpegDecContext, MJPEG_ST->pictureIn, &got_picture,
|
|
(uint8_t *) mjpegFrame, mjpegFrameLen);
|
|
|
|
if ((!got_picture) || (len == -1)){
|
|
motion_log(LOG_ERR,1,"mjpeg decoder: expected picture but didn't get it...");
|
|
return NULL;
|
|
}
|
|
|
|
// int wrap = pictureIn->linesize[0];
|
|
int xsize = MJPEG_ST->mjpegDecContext->width;
|
|
int ysize = MJPEG_ST->mjpegDecContext->height;
|
|
int pic_size = avpicture_get_size(MJPEG_ST->mjpegDecContext->pix_fmt, xsize, ysize);
|
|
|
|
if (pic_size != outbufSize) {
|
|
motion_log(LOG_ERR,1,"outbuf size mismatch. pic_size %i bufsize: %i",pic_size,outbufSize);
|
|
return NULL;
|
|
}
|
|
|
|
int size = avpicture_layout((AVPicture *)MJPEG_ST->pictureIn, MJPEG_ST->mjpegDecContext->pix_fmt,
|
|
xsize, ysize, outbuf, outbufSize);
|
|
|
|
if (size != outbufSize) {
|
|
motion_log(LOG_ERR,1,"mjpeg decoder: avpicture_layout error: size %i",size);
|
|
return NULL;
|
|
}
|
|
|
|
return outbuf;
|
|
}
|
|
|
|
void MJPEGStopDecoder(struct mjpeg *MJPEG_ST){
|
|
int got_picture;
|
|
|
|
// See if there is a last frame ... needed ?!
|
|
avcodec_decode_video(MJPEG_ST->mjpegDecContext, MJPEG_ST->pictureIn, &got_picture, NULL, 0);
|
|
|
|
if (MJPEG_ST->mjpegDecContext){
|
|
avcodec_close(MJPEG_ST->mjpegDecContext);
|
|
av_free(MJPEG_ST->mjpegDecContext);
|
|
MJPEG_ST->mjpegDecContext = 0;
|
|
}
|
|
|
|
if (MJPEG_ST->pictureIn)
|
|
av_free(MJPEG_ST->pictureIn);
|
|
|
|
MJPEG_ST->pictureIn = 0;
|
|
}
|
|
|
|
#endif
|