[FFmpeg-devel] [PATCH v1] avcodec/h264_mp4toannexb_bsf: force sps/pps writing before the first pict

Jun Li junli1026 at gmail.com
Sat Aug 17 02:13:22 EEST 2019


Fix #6869, write sps/pps before the first picture nal, no matter what type
of picture it is.
---
 libavcodec/h264_mp4toannexb_bsf.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/libavcodec/h264_mp4toannexb_bsf.c b/libavcodec/h264_mp4toannexb_bsf.c
index fb3f24ea40..e616c4c210 100644
--- a/libavcodec/h264_mp4toannexb_bsf.c
+++ b/libavcodec/h264_mp4toannexb_bsf.c
@@ -36,6 +36,7 @@ typedef struct H264BSFContext {
     uint8_t  idr_sps_seen;
     uint8_t  idr_pps_seen;
     int      extradata_parsed;
+    int      first_pict;
 } H264BSFContext;
 
 static int alloc_and_copy(AVPacket *out,
@@ -160,6 +161,7 @@ static int h264_mp4toannexb_init(AVBSFContext *ctx)
         s->idr_sps_seen     = 0;
         s->idr_pps_seen     = 0;
         s->extradata_parsed = 1;
+        s->first_pict       = 0;
     } else {
         av_log(ctx, AV_LOG_ERROR, "Invalid extradata size: %d\n", extra_size);
         return AVERROR_INVALIDDATA;
@@ -207,6 +209,9 @@ static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
         buf += s->length_size;
         unit_type = *buf & 0x1f;
 
+        if (!s->first_pict && (unit_type == H264_NAL_IDR_SLICE || unit_type == H264_NAL_SLICE))
+            s->first_pict = 1;
+
         if (nal_size > buf_end - buf || nal_size < 0)
             goto fail;
 
@@ -236,15 +241,15 @@ static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
         if (!s->new_idr && unit_type == H264_NAL_IDR_SLICE && (buf[1] & 0x80))
             s->new_idr = 1;
 
-        /* prepend only to the first type 5 NAL unit of an IDR picture, if no sps/pps are already present */
-        if (s->new_idr && unit_type == H264_NAL_IDR_SLICE && !s->idr_sps_seen && !s->idr_pps_seen) {
+        /* prepend only to the first type 5 NAL unit of an IDR picture or the first pict NAL of the entire stream, if no sps/pps are already present */
+        if ((s->new_idr && unit_type == H264_NAL_IDR_SLICE || s->first_pict == 1) && !s->idr_sps_seen && !s->idr_pps_seen) {
             if ((ret=alloc_and_copy(out,
                                ctx->par_out->extradata, ctx->par_out->extradata_size,
                                buf, nal_size, 1)) < 0)
                 goto fail;
             s->new_idr = 0;
         /* if only SPS has been seen, also insert PPS */
-        } else if (s->new_idr && unit_type == H264_NAL_IDR_SLICE && s->idr_sps_seen && !s->idr_pps_seen) {
+        } else if ((s->new_idr && unit_type == H264_NAL_IDR_SLICE || s->first_pict == 1) && s->idr_sps_seen && !s->idr_pps_seen) {
             if (s->pps_offset == -1) {
                 av_log(ctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n");
                 if ((ret = alloc_and_copy(out, NULL, 0, buf, nal_size, 0)) < 0)
@@ -263,6 +268,10 @@ static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
             }
         }
 
+        /* first picture has been found, set the flag to -1 */
+        if (s->first_pict == 1)
+            s->first_pict = -1;
+
 next_nal:
         buf        += nal_size;
         cumul_size += nal_size + s->length_size;
-- 
2.17.1



More information about the ffmpeg-devel mailing list