From 87046d69096e4d8a894a15c8ec371bac44004f6a Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Wed, 4 Sep 2019 15:40:05 +1000 Subject: [PATCH 1/3] ffmpeg: upgrade to version 4.2 --- package/ffmpeg/ffmpeg.hash | 2 +- package/ffmpeg/ffmpeg.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package/ffmpeg/ffmpeg.hash b/package/ffmpeg/ffmpeg.hash index f27eaa5706..1e03383055 100644 --- a/package/ffmpeg/ffmpeg.hash +++ b/package/ffmpeg/ffmpeg.hash @@ -1,5 +1,5 @@ # Locally calculated -sha256 f1f049a82fcfbf156564e73a3935d7e750891fab2abf302e735104fd4050a7e1 ffmpeg-4.1.4.tar.xz +sha256 023f10831a97ad93d798f53a3640e55cd564abfeba807ecbe8524dac4fedecd5 ffmpeg-4.2.tar.xz sha256 8177f97513213526df2cf6184d8ff986c675afb514d4e68a404010521b880643 COPYING.GPLv2 sha256 b634ab5640e258563c536e658cad87080553df6f34f62269a21d554844e58bfe COPYING.LGPLv2.1 sha256 73d99bc83313fff665b426d6672b4e0479102bc402fe22314ac9ce94a38aa5ff LICENSE.md diff --git a/package/ffmpeg/ffmpeg.mk b/package/ffmpeg/ffmpeg.mk index 349ed20822..89632ef282 100644 --- a/package/ffmpeg/ffmpeg.mk +++ b/package/ffmpeg/ffmpeg.mk @@ -4,7 +4,7 @@ # ################################################################################ -FFMPEG_VERSION = 4.1.4 +FFMPEG_VERSION = 4.2 FFMPEG_SOURCE = ffmpeg-$(FFMPEG_VERSION).tar.xz FFMPEG_SITE = http://ffmpeg.org/releases FFMPEG_INSTALL_STAGING = YES From 07e318b24f4c1d40ec78b581c6e78d1c69f97a4d Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Thu, 5 Sep 2019 14:31:27 +1000 Subject: [PATCH 2/3] ffmpeg: v4l2_m2m encoder: revert back to separate header mode --- ...se-joined-with-1st-frame-header-mode.patch | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 package/ffmpeg/1005-avcodec-v4l2-m2m-enc-use-joined-with-1st-frame-header-mode.patch diff --git a/package/ffmpeg/1005-avcodec-v4l2-m2m-enc-use-joined-with-1st-frame-header-mode.patch b/package/ffmpeg/1005-avcodec-v4l2-m2m-enc-use-joined-with-1st-frame-header-mode.patch deleted file mode 100644 index 4aea0ede30..0000000000 --- a/package/ffmpeg/1005-avcodec-v4l2-m2m-enc-use-joined-with-1st-frame-header-mode.patch +++ /dev/null @@ -1,19 +0,0 @@ -commit e370306deb9c48f4daa4ae4d622a7bd8b3828bef -Author: Joo Aun Saw -Date: Mon Aug 19 15:20:52 2019 +1000 - - avcodec/v4l2_m2m_enc: use joined with 1st frame header mode - -diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c -index 354d78babb..32aaaf18fb 100644 ---- a/libavcodec/v4l2_m2m_enc.c -+++ b/libavcodec/v4l2_m2m_enc.c -@@ -174,7 +174,7 @@ static int v4l2_prepare_encoder(V4L2m2mContext *s) - v4l2_set_timeperframe(s, avctx->framerate.num, avctx->framerate.den); - - /* set ext ctrls */ -- v4l2_set_ext_ctrl(s, MPEG_CID(HEADER_MODE), MPEG_VIDEO(HEADER_MODE_SEPARATE), "header mode"); -+ v4l2_set_ext_ctrl(s, MPEG_CID(HEADER_MODE), MPEG_VIDEO(HEADER_MODE_JOINED_WITH_1ST_FRAME), "header mode"); - /* enable bit rate control */ - if (avctx->bit_rate > 1) { - v4l2_set_ext_ctrl(s, MPEG_CID(FRAME_RC_ENABLE) , 1, "rate control"); From 022ad4e92d24c371514d902b5737b618c0f72631 Mon Sep 17 00:00:00 2001 From: Joo Aun Saw Date: Thu, 5 Sep 2019 14:32:36 +1000 Subject: [PATCH 3/3] motion: update patches to deal with v4l2m2m separate header mode --- package/motion/0002-enable-h264-v4l2m2m.patch | 168 +++++++++++++----- .../0003-ensure-first-frame-pts-zero.patch | 23 +++ .../0003-fix-h264-v4l2m2m-drain-error.patch | 35 ---- ...01-decouple-avcodec-send-and-receive.patch | 87 ++++++--- 4 files changed, 204 insertions(+), 109 deletions(-) create mode 100644 package/motion/0003-ensure-first-frame-pts-zero.patch delete mode 100644 package/motion/0003-fix-h264-v4l2m2m-drain-error.patch diff --git a/package/motion/0002-enable-h264-v4l2m2m.patch b/package/motion/0002-enable-h264-v4l2m2m.patch index 416ab8d279..2a3423c916 100644 --- a/package/motion/0002-enable-h264-v4l2m2m.patch +++ b/package/motion/0002-enable-h264-v4l2m2m.patch @@ -1,14 +1,49 @@ -commit cbf86207346d9f1bc36005c2a6342bacf4bcc3e4 -Author: Joo Aun Saw -Date: Mon Aug 19 16:33:08 2019 +1000 - - support h264_v4l2m2m encoder - diff --git a/ffmpeg.c b/ffmpeg.c -index 3f731ca..beb87b1 100644 +index 3f731ca..7a42d24 100644 --- a/ffmpeg.c +++ b/ffmpeg.c -@@ -555,7 +555,9 @@ static int ffmpeg_set_quality(struct ffmpeg *ffmpeg){ +@@ -179,6 +179,14 @@ int my_copy_packet(AVPacket *dest_pkt, AVPacket *src_pkt){ + #endif + } + /*********************************************/ ++void my_free_nal_info(struct ffmpeg *ffmpeg){ ++ if (ffmpeg->nal_info) { ++ free(ffmpeg->nal_info); ++ ffmpeg->nal_info = NULL; ++ ffmpeg->nal_info_len = 0; ++ } ++} ++/*********************************************/ + + /**************************************************************************** + **************************************************************************** +@@ -409,6 +417,25 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + return -1; + } + ++ if (ffmpeg->nal_info_separated) { ++ // h264_v4l2m2m has NAL units separated from the first frame, which makes ++ // some players very unhappy. ++ if ((ffmpeg->pkt.pts == 0) && (!(ffmpeg->pkt.flags & AV_PKT_FLAG_KEY))) { ++ my_free_nal_info(ffmpeg); ++ ffmpeg->nal_info_len = ffmpeg->pkt.size; ++ ffmpeg->nal_info = malloc(ffmpeg->nal_info_len); ++ if (ffmpeg->nal_info) ++ memcpy(ffmpeg->nal_info, &ffmpeg->pkt.data[0], ffmpeg->nal_info_len); ++ else ++ ffmpeg->nal_info_len = 0; ++ } else if (ffmpeg->nal_info) { ++ int old_size = ffmpeg->pkt.size; ++ av_grow_packet(&ffmpeg->pkt, ffmpeg->nal_info_len); ++ memmove(&ffmpeg->pkt.data[ffmpeg->nal_info_len], &ffmpeg->pkt.data[0], old_size); ++ memcpy(&ffmpeg->pkt.data[0], ffmpeg->nal_info, ffmpeg->nal_info_len); ++ my_free_nal_info(ffmpeg); ++ } ++ } + return 0; + + #elif (LIBAVFORMAT_VERSION_MAJOR >= 55) || ((LIBAVFORMAT_VERSION_MAJOR == 54) && (LIBAVFORMAT_VERSION_MINOR > 6)) +@@ -555,7 +582,9 @@ static int ffmpeg_set_quality(struct ffmpeg *ffmpeg){ ffmpeg->quality = 45; // default to 45% quality av_dict_set(&ffmpeg->opts, "preset", "ultrafast", 0); av_dict_set(&ffmpeg->opts, "tune", "zerolatency", 0); @@ -19,7 +54,7 @@ index 3f731ca..beb87b1 100644 // H264 OMX encoder quality can only be controlled via bit_rate // bit_rate = ffmpeg->width * ffmpeg->height * ffmpeg->fps * quality_factor ffmpeg->quality = (int)(((int64_t)ffmpeg->width * ffmpeg->height * ffmpeg->fps * ffmpeg->quality) >> 7); -@@ -702,7 +708,10 @@ static int ffmpeg_set_codec(struct ffmpeg *ffmpeg){ +@@ -702,13 +731,20 @@ static int ffmpeg_set_codec(struct ffmpeg *ffmpeg){ ffmpeg->ctx_codec->height = ffmpeg->height; ffmpeg->ctx_codec->time_base.num = 1; ffmpeg->ctx_codec->time_base.den = ffmpeg->fps; @@ -31,12 +66,22 @@ index 3f731ca..beb87b1 100644 ffmpeg->ctx_codec->max_b_frames = 0; if (strcmp(ffmpeg->codec_name, "ffv1") == 0){ ffmpeg->ctx_codec->strict_std_compliance = -2; -@@ -768,6 +777,65 @@ static int ffmpeg_set_stream(struct ffmpeg *ffmpeg){ + ffmpeg->ctx_codec->level = 3; + } + ffmpeg->ctx_codec->flags |= MY_CODEC_FLAG_GLOBAL_HEADER; ++ // h264_v4l2m2m has NAL units separated from the first frame. We need to deal ++ // with it appriopriately later ++ if (strcmp(ffmpeg->codec->name, "h264_v4l2m2m") == 0) ++ ffmpeg->nal_info_separated = 1; + + retcd = ffmpeg_set_quality(ffmpeg); + if (retcd < 0){ +@@ -768,8 +804,69 @@ static int ffmpeg_set_stream(struct ffmpeg *ffmpeg){ } + -+static int alloc_video_buffer(AVFrame *frame, int align) ++static int ffmpeg_alloc_video_buffer(AVFrame *frame, int align) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); + int ret, i, padded_height; @@ -73,12 +118,14 @@ index 3f731ca..beb87b1 100644 + frame->buf[0] = av_buffer_alloc(ret + 4*plane_padding); + if (!frame->buf[0]) { + ret = AVERROR(ENOMEM); -+ goto fail; ++ av_frame_unref(frame); ++ return ret; + } + frame->buf[1] = av_buffer_alloc(ret + 4*plane_padding); + if (!frame->buf[1]) { + ret = AVERROR(ENOMEM); -+ goto fail; ++ av_frame_unref(frame); ++ return ret; + } + + frame->data[0] = frame->buf[0]->data; @@ -88,23 +135,27 @@ index 3f731ca..beb87b1 100644 + frame->extended_data = frame->data; + + return 0; -+fail: -+ av_frame_unref(frame); -+ return ret; +} + + static int ffmpeg_set_picture(struct ffmpeg *ffmpeg){ ++ int retcd; ++ char errstr[128]; ++ ffmpeg->picture = my_frame_alloc(); -@@ -789,6 +857,15 @@ static int ffmpeg_set_picture(struct ffmpeg *ffmpeg){ + if (!ffmpeg->picture) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("could not alloc frame")); +@@ -789,6 +886,17 @@ static int ffmpeg_set_picture(struct ffmpeg *ffmpeg){ ffmpeg->picture->width = ffmpeg->ctx_codec->width; ffmpeg->picture->height = ffmpeg->ctx_codec->height; + // h264_v4l2m2m encoder expects video buffer to be allocated + if (strcmp(ffmpeg->codec->name, "h264_v4l2m2m") == 0) { -+ if (alloc_video_buffer(ffmpeg->picture, 32)) { -+ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("could not alloc buffers")); ++ retcd = ffmpeg_alloc_video_buffer(ffmpeg->picture, 32); ++ if (retcd) { ++ av_strerror(retcd, errstr, sizeof(errstr)); ++ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("could not alloc buffers %s"), errstr); + ffmpeg_free_context(ffmpeg); + return -1; + } @@ -113,45 +164,70 @@ index 3f731ca..beb87b1 100644 return 0; } -@@ -1365,9 +1442,38 @@ int ffmpeg_put_image(struct ffmpeg *ffmpeg, struct image_data *img_data, const s +@@ -891,6 +999,12 @@ static int ffmpeg_flush_codec(struct ffmpeg *ffmpeg){ + my_packet_unref(ffmpeg->pkt); + return -1; + } ++ // v4l2_m2m encoder uses pts 0 and size 0 to indicate AVERROR_EOF ++ if ((ffmpeg->pkt.pts == 0) || (ffmpeg->pkt.size == 0)) { ++ recv_cd = AVERROR_EOF; ++ my_packet_unref(ffmpeg->pkt); ++ continue; ++ } + retcd = av_write_frame(ffmpeg->oc, &ffmpeg->pkt); + if (retcd < 0) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO +@@ -1339,6 +1453,7 @@ void ffmpeg_close(struct ffmpeg *ffmpeg){ + } + } + ffmpeg_free_context(ffmpeg); ++ my_free_nal_info(ffmpeg); + } + + #else +@@ -1365,9 +1480,28 @@ int ffmpeg_put_image(struct ffmpeg *ffmpeg, struct image_data *img_data, const s } /* Setup pointers and line widths. */ - ffmpeg->picture->data[0] = image; - ffmpeg->picture->data[1] = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height); - ffmpeg->picture->data[2] = ffmpeg->picture->data[1] + ((ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height) / 4); -+ // Some encoders look for the image in ffmpeg->picture->buf -+ if (ffmpeg->picture->buf[0] == NULL) -+ ffmpeg->picture->data[0] = image; -+ else -+ memcpy(ffmpeg->picture->data[0], image, ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height); -+ -+ if (ffmpeg->picture->buf[1] == NULL) { -+ // assume YUV420P format -+ ffmpeg->picture->data[1] = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height); -+ ffmpeg->picture->data[2] = ffmpeg->picture->data[1] + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height / 4); -+ } else { ++ if (strcmp(ffmpeg->codec->name, "h264_v4l2m2m") == 0) { ++ // assume NV21 format + int cr_len = ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height / 4; -+ int cb_len = cr_len; + unsigned char *imagecr = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height); + unsigned char *imagecb = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height) + cr_len; -+ if (ffmpeg->ctx_codec->pix_fmt == AV_PIX_FMT_NV21) { -+ int x; -+ int y; -+ for (y = 0; y < ffmpeg->ctx_codec->height; y++) { -+ for (x = 0; x < ffmpeg->ctx_codec->width/4; x++) { -+ ffmpeg->picture->data[1][y*ffmpeg->ctx_codec->width/2 + x*2] = *imagecb; -+ ffmpeg->picture->data[1][y*ffmpeg->ctx_codec->width/2 + x*2 + 1] = *imagecr; -+ imagecb++; -+ imagecr++; -+ } ++ int x; ++ int y; ++ memcpy(ffmpeg->picture->data[0], image, ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height); ++ for (y = 0; y < ffmpeg->ctx_codec->height; y++) { ++ for (x = 0; x < ffmpeg->ctx_codec->width/4; x++) { ++ ffmpeg->picture->data[1][y*ffmpeg->ctx_codec->width/2 + x*2] = *imagecb; ++ ffmpeg->picture->data[1][y*ffmpeg->ctx_codec->width/2 + x*2 + 1] = *imagecr; ++ imagecb++; ++ imagecr++; + } -+ } else { -+ // assume YUV420P format -+ memcpy(&ffmpeg->picture->data[1][0], imagecr, cr_len); -+ memcpy(&ffmpeg->picture->data[1][cr_len], imagecb, cb_len); + } ++ } else { ++ // assume YUV420P format ++ ffmpeg->picture->data[0] = image; ++ ffmpeg->picture->data[1] = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height); ++ ffmpeg->picture->data[2] = ffmpeg->picture->data[1] + ((ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height) / 4); + } ffmpeg->gop_cnt ++; if (ffmpeg->gop_cnt == ffmpeg->ctx_codec->gop_size ){ +diff --git a/ffmpeg.h b/ffmpeg.h +index ca77430..c4ae7bb 100644 +--- a/ffmpeg.h ++++ b/ffmpeg.h +@@ -61,6 +61,9 @@ struct ffmpeg { + int high_resolution; + int motion_images; + int passthrough; ++ int nal_info_separated; ++ char *nal_info; ++ int nal_info_len; + }; + #else + struct ffmpeg { diff --git a/package/motion/0003-ensure-first-frame-pts-zero.patch b/package/motion/0003-ensure-first-frame-pts-zero.patch new file mode 100644 index 0000000000..56b0d6c19c --- /dev/null +++ b/package/motion/0003-ensure-first-frame-pts-zero.patch @@ -0,0 +1,23 @@ +commit 0cd12918f93fc6559dad56d176a60ddc3f0844d6 +Author: Joo Aun Saw +Date: Thu Sep 5 14:20:07 2019 +1000 + + ffmpeg: ensure first frame PTS is zero + +diff --git a/ffmpeg.c b/ffmpeg.c +index 7a42d24..665aa00 100644 +--- a/ffmpeg.c ++++ b/ffmpeg.c +@@ -512,7 +512,11 @@ static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ + ffmpeg_reset_movie_start_time(ffmpeg, tv1); + pts_interval = 0; + } +- ffmpeg->picture->pts = av_rescale_q(pts_interval,(AVRational){1, 1000000L},ffmpeg->video_st->time_base) + ffmpeg->base_pts; ++ if (ffmpeg->last_pts < 0) { ++ // This is the very first frame, ensure PTS is zero ++ ffmpeg->picture->pts = 0; ++ } else ++ ffmpeg->picture->pts = av_rescale_q(pts_interval,(AVRational){1, 1000000L},ffmpeg->video_st->time_base) + ffmpeg->base_pts; + + if (ffmpeg->test_mode == TRUE){ + MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO diff --git a/package/motion/0003-fix-h264-v4l2m2m-drain-error.patch b/package/motion/0003-fix-h264-v4l2m2m-drain-error.patch deleted file mode 100644 index 0937f8f9a6..0000000000 --- a/package/motion/0003-fix-h264-v4l2m2m-drain-error.patch +++ /dev/null @@ -1,35 +0,0 @@ -commit d1aad9ec2b37560ddf2b2a362e30882adce8fb94 -Author: Joo Aun Saw -Date: Mon Aug 19 16:36:30 2019 +1000 - - fix h264_v4l2m2m encoder draining error - - When h264_v4l2m2m encoder is drained, it sets packet pts and size to - zero rather than returning AVERROR_EOF. - -diff --git a/ffmpeg.c b/ffmpeg.c -index beb87b1..a3a8701 100644 ---- a/ffmpeg.c -+++ b/ffmpeg.c -@@ -968,11 +968,16 @@ static int ffmpeg_flush_codec(struct ffmpeg *ffmpeg){ - my_packet_unref(ffmpeg->pkt); - return -1; - } -- retcd = av_write_frame(ffmpeg->oc, &ffmpeg->pkt); -- if (retcd < 0) { -- MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO -- ,_("Error writing draining video frame")); -- return -1; -+ // v4l2_m2m encoder uses pts 0 and size 0 to indicate AVERROR_EOF -+ if ((ffmpeg->pkt.pts > 0) && (ffmpeg->pkt.size > 0)) { -+ retcd = av_write_frame(ffmpeg->oc, &ffmpeg->pkt); -+ if (retcd < 0) { -+ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO -+ ,_("Error writing draining video frame")); -+ return -1; -+ } -+ } else { -+ recv_cd = AVERROR_EOF; - } - } - my_packet_unref(ffmpeg->pkt); diff --git a/package/motion/1001-decouple-avcodec-send-and-receive.patch b/package/motion/1001-decouple-avcodec-send-and-receive.patch index 54e9c4a493..cf35ada2e0 100644 --- a/package/motion/1001-decouple-avcodec-send-and-receive.patch +++ b/package/motion/1001-decouple-avcodec-send-and-receive.patch @@ -1,19 +1,12 @@ -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 +index 665aa00..1246fdc 100644 --- a/ffmpeg.c +++ b/ffmpeg.c -@@ -378,6 +378,15 @@ static int ffmpeg_get_oformat(struct ffmpeg *ffmpeg){ +@@ -386,6 +386,14 @@ 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 { @@ -24,7 +17,7 @@ index 6b5459d..18b2894 100644 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){ +@@ -400,41 +408,49 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ ,_("Error sending frame for encoding:%s"),errstr); return -1; } @@ -34,7 +27,34 @@ index 6b5459d..18b2894 100644 - av_strerror(retcd, errstr, sizeof(errstr)); - MOTION_LOG(DBG, TYPE_ENCODER, NO_ERRNO - ,_("Receive packet threw EAGAIN returning -2 code :%s"),errstr); -+ +- 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->nal_info_separated) { +- // h264_v4l2m2m has NAL units separated from the first frame, which makes +- // some players very unhappy. +- if ((ffmpeg->pkt.pts == 0) && (!(ffmpeg->pkt.flags & AV_PKT_FLAG_KEY))) { +- my_free_nal_info(ffmpeg); +- ffmpeg->nal_info_len = ffmpeg->pkt.size; +- ffmpeg->nal_info = malloc(ffmpeg->nal_info_len); +- if (ffmpeg->nal_info) +- memcpy(ffmpeg->nal_info, &ffmpeg->pkt.data[0], ffmpeg->nal_info_len); +- else +- ffmpeg->nal_info_len = 0; +- } else if (ffmpeg->nal_info) { +- int old_size = ffmpeg->pkt.size; +- av_grow_packet(&ffmpeg->pkt, ffmpeg->nal_info_len); +- memmove(&ffmpeg->pkt.data[ffmpeg->nal_info_len], &ffmpeg->pkt.data[0], old_size); +- memcpy(&ffmpeg->pkt.data[0], ffmpeg->nal_info, ffmpeg->nal_info_len); +- my_free_nal_info(ffmpeg); + while (retcd >= 0) { + av_init_packet(&ffmpeg->pkt); + ffmpeg->pkt.data = NULL; @@ -44,13 +64,32 @@ index 6b5459d..18b2894 100644 + //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->nal_info_separated) { ++ // h264_v4l2m2m has NAL units separated from the first frame, which makes ++ // some players very unhappy. ++ if ((ffmpeg->pkt.pts == 0) && (!(ffmpeg->pkt.flags & AV_PKT_FLAG_KEY))) { ++ my_free_nal_info(ffmpeg); ++ ffmpeg->nal_info_len = ffmpeg->pkt.size; ++ ffmpeg->nal_info = malloc(ffmpeg->nal_info_len); ++ if (ffmpeg->nal_info) ++ memcpy(ffmpeg->nal_info, &ffmpeg->pkt.data[0], ffmpeg->nal_info_len); ++ else ++ ffmpeg->nal_info_len = 0; ++ } else if (ffmpeg->nal_info) { ++ int old_size = ffmpeg->pkt.size; ++ av_grow_packet(&ffmpeg->pkt, ffmpeg->nal_info_len); ++ memmove(&ffmpeg->pkt.data[ffmpeg->nal_info_len], &ffmpeg->pkt.data[0], old_size); ++ memcpy(&ffmpeg->pkt.data[0], ffmpeg->nal_info, ffmpeg->nal_info_len); ++ my_free_nal_info(ffmpeg); ++ } ++ } + if (ffmpeg_write_packet(ffmpeg) < 0) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "Error while writing video frame"); + my_packet_unref(ffmpeg->pkt); @@ -58,19 +97,11 @@ index 6b5459d..18b2894 100644 + 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; ++ my_packet_unref(ffmpeg->pkt); } - return 0; -@@ -417,11 +436,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ + +@@ -444,11 +460,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ char errstr[128]; int got_packet_ptr; @@ -87,7 +118,7 @@ index 6b5459d..18b2894 100644 return -1; } if (got_packet_ptr == 0){ -@@ -430,6 +453,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -457,6 +477,15 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ return -2; } @@ -103,7 +134,7 @@ index 6b5459d..18b2894 100644 return 0; #else -@@ -438,6 +470,10 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ +@@ -465,6 +494,10 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ uint8_t *video_outbuf; int video_outbuf_size; @@ -114,7 +145,7 @@ index 6b5459d..18b2894 100644 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){ +@@ -490,6 +523,17 @@ static int ffmpeg_encode_video(struct ffmpeg *ffmpeg){ ffmpeg->pkt.pts = ffmpeg->picture->pts; ffmpeg->pkt.dts = ffmpeg->pkt.pts; @@ -132,7 +163,7 @@ index 6b5459d..18b2894 100644 free(video_outbuf); return 0; -@@ -1000,14 +1047,9 @@ static int ffmpeg_flush_codec(struct ffmpeg *ffmpeg){ +@@ -1034,14 +1078,9 @@ static int ffmpeg_flush_codec(struct ffmpeg *ffmpeg){ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ int retcd; @@ -147,7 +178,7 @@ index 6b5459d..18b2894 100644 return 0; } -@@ -1016,21 +1058,9 @@ static int ffmpeg_put_frame(struct ffmpeg *ffmpeg, const struct timeval *tv1){ +@@ -1050,21 +1089,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")); }