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

Submitted by Jun Li on Aug. 16, 2019, 11:05 p.m.

Details

Message ID CA+ihTq=SrDJyV3+S+rsZSzhFcTB08iZYx3fvyK1EGAfW1hM7Rg@mail.gmail.com
State New
Headers show

Commit Message

Jun Li Aug. 16, 2019, 11:05 p.m.
Hi,
This patch is trying to fix #6869.
The ticket has a h264 stream NOT starting with IDR, and all frames are I
frames.
And the mp4toannexb filter insert SPS/PPS before IDR, so leads to the
result that the output has no SPS/PPS.

The fix is just simply insert SPS/PPS before first picture, no matter what
type it is. Thanks.

Best Regards
-Jun

Patch hide | download patch | download mbox

From 052674e9d4e2e6cf29141858b6cdc707fb75ecb1 Mon Sep 17 00:00:00 2001
From: Jun Li <junli1026@gmail.com>
Date: Fri, 16 Aug 2019 15:08:23 -0700
Subject: [PATCH v1] avcodec/h264_mp4toannexb_bsf: force sps/pps writing before
 the first pict

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