diff --git a/package/motion/1001-decouple-avcodec-send-and-receive.patch b/package/motion/1001-decouple-avcodec-send-and-receive.patch new file mode 100644 index 0000000000..54e9c4a493 --- /dev/null +++ b/package/motion/1001-decouple-avcodec-send-and-receive.patch @@ -0,0 +1,171 @@ +commit b9b521dc5d6179e8570d826e00728130144e3902 +Author: Joo Aun Saw +Date: Tue Aug 27 01:09:43 2019 +1000 + + ffmpeg: decouple avcodec send and receive + +diff --git a/ffmpeg.c b/ffmpeg.c +index 6b5459d..18b2894 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -378,6 +378,15 @@ static int ffmpeg_get_oformat(struct ffmpeg *ffmpeg){ + return 0; + } + ++static int ffmpeg_write_packet(struct ffmpeg *ffmpeg){ ++ ++ if (ffmpeg->tlapse == TIMELAPSE_APPEND) { ++ return ffmpeg_timelapse_append(ffmpeg, ffmpeg->pkt); ++ } else { ++ return av_write_frame(ffmpeg->oc, &ffmpeg->pkt); ++ } ++} ++ + static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + + #if (LIBAVFORMAT_VERSION_MAJOR >= 58) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR >= 41)) +@@ -392,21 +401,31 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + ,_("Error sending frame for encoding:%s"),errstr); + return -1; + } +- retcd = avcodec_receive_packet(ffmpeg->ctx_codec, &ffmpeg->pkt); +- if (retcd == AVERROR(EAGAIN)){ +- //Buffered packet. Throw special return code +- av_strerror(retcd, errstr, sizeof(errstr)); +- MOTION_LOG(DBG, TYPE_ENCODER, NO_ERRNO +- ,_("Receive packet threw EAGAIN returning -2 code :%s"),errstr); ++ ++ while (retcd >= 0) { ++ av_init_packet(&ffmpeg->pkt); ++ ffmpeg->pkt.data = NULL; ++ ffmpeg->pkt.size = 0; ++ retcd = avcodec_receive_packet(ffmpeg->ctx_codec, &ffmpeg->pkt); ++ if (retcd == AVERROR(EAGAIN)){ ++ //Buffered packet. Throw special return code ++ my_packet_unref(ffmpeg->pkt); ++ return -2; ++ } ++ if (retcd < 0 ){ ++ av_strerror(retcd, errstr, sizeof(errstr)); ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error receiving encoded packet video:%s",errstr); ++ my_packet_unref(ffmpeg->pkt); ++ return -1; ++ } else { ++ if (ffmpeg_write_packet(ffmpeg) < 0) { ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); ++ my_packet_unref(ffmpeg->pkt); ++ ffmpeg_free_context(ffmpeg); ++ return -1; ++ } ++ } + my_packet_unref(ffmpeg->pkt); +- return -2; +- } +- if (retcd < 0 ){ +- av_strerror(retcd, errstr, sizeof(errstr)); +- MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO +- ,_("Error receiving encoded packet video:%s"),errstr); +- //Packet is freed upon failure of encoding +- return -1; + } + + return 0; +@@ -417,11 +436,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + char errstr[128]; + int got_packet_ptr; + ++ av_init_packet(&ffmpeg->pkt); ++ ffmpeg->pkt.data = NULL; ++ ffmpeg->pkt.size = 0; ++ + retcd = avcodec_encode_video2(ffmpeg->ctx_codec, &ffmpeg->pkt, ffmpeg->picture, &got_packet_ptr); + if (retcd < 0 ){ + av_strerror(retcd, errstr, sizeof(errstr)); + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Error encoding video:%s"),errstr); +- //Packet is freed upon failure of encoding ++ my_packet_unref(ffmpeg->pkt); + return -1; + } + if (got_packet_ptr == 0){ +@@ -430,6 +453,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + return -2; + } + ++ retcd = ffmpeg_write_packet(ffmpeg); ++ if (retcd < 0) { ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); ++ my_packet_unref(ffmpeg->pkt); ++ ffmpeg_free_context(ffmpeg); ++ return -1; ++ } ++ my_packet_unref(ffmpeg->pkt); ++ + return 0; + + #else +@@ -438,6 +470,10 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + uint8_t *video_outbuf; + int video_outbuf_size; + ++ av_init_packet(&ffmpeg->pkt); ++ ffmpeg->pkt.data = NULL; ++ ffmpeg->pkt.size = 0; ++ + video_outbuf_size = (ffmpeg->ctx_codec->width +16) * (ffmpeg->ctx_codec->height +16) * 1; + video_outbuf = mymalloc(video_outbuf_size); + +@@ -463,6 +499,17 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + ffmpeg->pkt.pts = ffmpeg->picture->pts; + ffmpeg->pkt.dts = ffmpeg->pkt.pts; + ++ retcd = ffmpeg_write_packet(ffmpeg); ++ if (retcd < 0) { ++ av_strerror(retcd, errstr, sizeof(errstr)); ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); ++ my_packet_unref(ffmpeg->pkt); ++ free(video_outbuf); ++ ffmpeg_free_context(ffmpeg); ++ return -1; ++ } ++ ++ my_packet_unref(ffmpeg->pkt); + free(video_outbuf); + + return 0; +@@ -1000,14 +1047,9 @@ static int ffmpeg_flush_codec(struct ffmpeg *ffmpeg){ + static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + int retcd; + +- av_init_packet(&ffmpeg->pkt); +- ffmpeg->pkt.data = NULL; +- ffmpeg->pkt.size = 0; +- + retcd = ffmpeg_set_pts(ffmpeg, tv1); + if (retcd < 0) { + //If there is an error, it has already been reported. +- my_packet_unref(ffmpeg->pkt); + return 0; + } + +@@ -1016,21 +1058,9 @@ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + if (retcd != -2){ + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Error while encoding picture")); + } +- my_packet_unref(ffmpeg->pkt); + return retcd; + } + +- if (ffmpeg->tlapse == TIMELAPSE_APPEND) { +- retcd = ffmpeg_timelapse_append(ffmpeg, ffmpeg->pkt); +- } else { +- retcd = av_write_frame(ffmpeg->oc, &ffmpeg->pkt); +- } +- my_packet_unref(ffmpeg->pkt); +- +- if (retcd < 0) { +- MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Error while writing video frame")); +- return -1; +- } + return retcd; + + }