motion: decouple avcodec send and receive

This commit is contained in:
Joo Aun Saw 2019-08-27 01:37:15 +10:00
parent bbbc89cca9
commit ee9e54d45d

View File

@ -0,0 +1,171 @@
commit b9b521dc5d6179e8570d826e00728130144e3902
Author: Joo Aun Saw <jasaw@dius.com.au>
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;
}