diff --git a/package/motion/0010-set-pts-before-encode.patch b/package/motion/0010-set-pts-before-encode.patch new file mode 100644 index 0000000000..87ca85a7bb --- /dev/null +++ b/package/motion/0010-set-pts-before-encode.patch @@ -0,0 +1,76 @@ +commit 2c072634efd8e3b7fb70a1d85cd54e9befe96dd2 +Author: Joo Aun Saw +Date: Tue Sep 5 11:09:41 2017 +1000 + + set PTS value before encoding + +diff --git a/ffmpeg.c b/ffmpeg.c +index 87b4f75..739bcb3 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -419,8 +419,7 @@ static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + + if (ffmpeg->tlapse != TIMELAPSE_NONE) { + ffmpeg->last_pts++; +- ffmpeg->pkt.pts = ffmpeg->last_pts; +- ffmpeg->pkt.dts = ffmpeg->last_pts; ++ ffmpeg->picture->pts = ffmpeg->last_pts; + } else { + pts_interval = ((1000000L * (tv1->tv_sec - ffmpeg->start_time.tv_sec)) + tv1->tv_usec - ffmpeg->start_time.tv_usec); + if (pts_interval < 0){ +@@ -428,23 +427,22 @@ static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + ffmpeg_reset_movie_start_time(ffmpeg, tv1); + pts_interval = 0; + } +- ffmpeg->pkt.pts = av_rescale_q(pts_interval,(AVRational){1, 1000000L},ffmpeg->video_st->time_base) + ffmpeg->base_pts; ++ ffmpeg->picture->pts = av_rescale_q(pts_interval,(AVRational){1, 1000000L},ffmpeg->video_st->time_base) + ffmpeg->base_pts; + + if (ffmpeg->test_mode == 1){ + MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, "PTS %"PRId64" Base PTS %"PRId64" ms interval %"PRId64" timebase %d-%d", +- ffmpeg->pkt.pts,ffmpeg->base_pts,pts_interval, ++ ffmpeg->picture->pts,ffmpeg->base_pts,pts_interval, + ffmpeg->video_st->time_base.num,ffmpeg->video_st->time_base.den); + } + +- if (ffmpeg->pkt.pts <= ffmpeg->last_pts){ ++ if (ffmpeg->picture->pts <= ffmpeg->last_pts){ + //We have a problem with our motion loop timing and sending frames or the rounding into the PTS. + if (ffmpeg->test_mode == 1){ + MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, "BAD TIMING!! Frame skipped."); + } + return -1; + } +- ffmpeg->pkt.dts = ffmpeg->pkt.pts; +- ffmpeg->last_pts = ffmpeg->pkt.pts; ++ ffmpeg->last_pts = ffmpeg->picture->pts; + } + return 0; + } +@@ -703,13 +701,6 @@ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + ffmpeg->pkt.data = NULL; + ffmpeg->pkt.size = 0; + +- retcd = ffmpeg_encode_video(ffmpeg); +- if (retcd != 0){ +- MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while encoding picture"); +- my_packet_unref(ffmpeg->pkt); +- return retcd; +- } +- + retcd = ffmpeg_set_pts(ffmpeg, tv1); + if (retcd < 0) { + //If there is an error, it has already been reported. +@@ -717,6 +708,13 @@ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + return -1; + } + ++ retcd = ffmpeg_encode_video(ffmpeg); ++ if (retcd != 0){ ++ 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 { diff --git a/package/motion/0011-decouple-avcodec-send-receive.patch b/package/motion/0011-decouple-avcodec-send-receive.patch new file mode 100644 index 0000000000..48becbe9e5 --- /dev/null +++ b/package/motion/0011-decouple-avcodec-send-receive.patch @@ -0,0 +1,176 @@ +diff --git a/ffmpeg.c b/ffmpeg.c +index 739bcb3..0e44c97 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -324,6 +324,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)) +@@ -331,27 +340,41 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + int retcd = 0; + char errstr[128]; + ++ av_init_packet(&ffmpeg->pkt); ++ ffmpeg->pkt.data = NULL; ++ ffmpeg->pkt.size = 0; ++ + retcd = avcodec_send_frame(ffmpeg->ctx_codec, ffmpeg->picture); + if (retcd < 0 ){ + av_strerror(retcd, errstr, sizeof(errstr)); + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "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 + 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; + } +- if (ffmpeg->picture->key_frame == 1) +- ffmpeg->pkt.flags |= AV_PKT_FLAG_KEY; ++ while (retcd >= 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 { ++ 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; + + #elif (LIBAVFORMAT_VERSION_MAJOR >= 55) || ((LIBAVFORMAT_VERSION_MAJOR == 54) && (LIBAVFORMAT_VERSION_MINOR > 6)) +@@ -360,11 +383,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){ +@@ -376,6 +403,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + if (ffmpeg->picture->key_frame == 1) + ffmpeg->pkt.flags |= AV_PKT_FLAG_KEY; + ++ 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 +@@ -384,6 +420,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); + +@@ -407,6 +447,16 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + + free(video_outbuf); + ++ 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); ++ ffmpeg_free_context(ffmpeg); ++ return -1; ++ } ++ ++ my_packet_unref(ffmpeg->pkt); + return 0; + + #endif +@@ -697,36 +747,18 @@ static int ffmpeg_set_outputfile(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 -1; + } + + retcd = ffmpeg_encode_video(ffmpeg); +- if (retcd != 0){ +- 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); ++ if (retcd < 0){ ++ if (retcd != -2) ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while encoding picture"); + } +- my_packet_unref(ffmpeg->pkt); + +- if (retcd < 0) { +- MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); +- ffmpeg_free_context(ffmpeg); +- return -1; +- } + return retcd; + + } diff --git a/package/motion/0012-drain-codec.patch b/package/motion/0012-drain-codec.patch new file mode 100644 index 0000000000..3350e6a16d --- /dev/null +++ b/package/motion/0012-drain-codec.patch @@ -0,0 +1,68 @@ +diff --git a/ffmpeg.c b/ffmpeg.c +index 0e44c97..e5a2b9e 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -463,6 +463,55 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + + } + ++static int ffmpeg_drain_codec(struct ffmpeg *ffmpeg){ ++ ++#if (LIBAVFORMAT_VERSION_MAJOR >= 58) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR >= 41)) ++ //ffmpeg version 3.1 and after ++ int retcd = 0; ++ char errstr[128]; ++ ++ av_init_packet(&ffmpeg->pkt); ++ ffmpeg->pkt.data = NULL; ++ ffmpeg->pkt.size = 0; ++ ++ retcd = avcodec_send_frame(ffmpeg->ctx_codec, NULL); ++ if (retcd < 0 ){ ++ av_strerror(retcd, errstr, sizeof(errstr)); ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error draining codec:%s",errstr); ++ my_packet_unref(ffmpeg->pkt); ++ return -1; ++ } ++ for (;;) { ++ retcd = avcodec_receive_packet(ffmpeg->ctx_codec, &ffmpeg->pkt); ++ if (retcd == AVERROR_EOF) ++ break; ++ 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 { ++ 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); ++ return -1; ++ } ++ } ++ } ++ ++ my_packet_unref(ffmpeg->pkt); ++ return 0; ++ ++#else ++ ++ // do nothing ++ return 0; ++ ++#endif ++ ++} ++ + static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + + int64_t pts_interval; +@@ -894,6 +943,7 @@ void ffmpeg_close(struct ffmpeg *ffmpeg){ + #ifdef HAVE_FFMPEG + + if (ffmpeg != NULL) { ++ ffmpeg_drain_codec(ffmpeg); + if (ffmpeg->tlapse != TIMELAPSE_APPEND) { + av_write_trailer(ffmpeg->oc); + }