[FFmpeg-devel] [PATCH 2/6] avcodec/extract_extradata_bsf: use the parsing code from h264_split()

James Almer jamrial at gmail.com
Sat Mar 25 00:31:43 EET 2017


The current code discards every non SPS/PPS NAL from extradata, which even if
in theory they aren't needed there, some samples fail to decode without them,
like "11159 HD-PVR sample.mpg".

Signed-off-by: James Almer <jamrial at gmail.com>
---
Someone who wants to look why those filtered NALs are needed by such samples,
or if there's some problem in the ff_h2645_packet_split() based parsing code,
would come in handy and be very welcome.

 libavcodec/extract_extradata_bsf.c | 66 ++++++++++++++++++++++++++++++--------
 1 file changed, 52 insertions(+), 14 deletions(-)

diff --git a/libavcodec/extract_extradata_bsf.c b/libavcodec/extract_extradata_bsf.c
index d909ee6d17..bb2e9bf68c 100644
--- a/libavcodec/extract_extradata_bsf.c
+++ b/libavcodec/extract_extradata_bsf.c
@@ -49,15 +49,58 @@ static int val_in_array(const int *arr, int len, int val)
     return 0;
 }
 
-static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt,
-                                   uint8_t **data, int *size)
+static int extract_extradata_h264(AVBSFContext *ctx, AVPacket *pkt,
+                                  uint8_t **data, int *size)
+{
+    ExtractExtradataContext *s = ctx->priv_data;
+    uint32_t state = UINT32_MAX;
+    const uint8_t *ptr = pkt->data, *end = pkt->data + pkt->size;
+    int has_sps    = 0;
+    int has_pps    = 0;
+    int nalu_type;
+
+    while (ptr < end) {
+        ptr = avpriv_find_start_code(ptr, end, &state);
+        if ((state & 0xFFFFFF00) != 0x100)
+            break;
+        nalu_type = state & 0x1F;
+        if (nalu_type == H264_NAL_SPS) {
+            has_sps = 1;
+        } else if (nalu_type == H264_NAL_PPS)
+            has_pps = 1;
+        else if ((nalu_type != H264_NAL_SEI || has_pps) &&
+                  nalu_type != H264_NAL_AUD && nalu_type != H264_NAL_SPS_EXT &&
+                  nalu_type != 0x0f) {
+            if (has_sps) {
+                while (ptr - 4 > pkt->data && ptr[-5] == 0)
+                    ptr--;
+                if (ptr - pkt->data > 4) {
+                    *size = ptr - 4 - pkt->data;
+                    *data = av_malloc(*size + AV_INPUT_BUFFER_PADDING_SIZE);
+                    if (!*data)
+                        return AVERROR(ENOMEM);
+
+                    memcpy(*data, pkt->data, *size);
+
+                    if (s->remove) {
+                        pkt->data += *size;
+                        pkt->size -= *size;
+                    }
+                }
+                return 0;
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int extract_extradata_h265(AVBSFContext *ctx, AVPacket *pkt,
+                                  uint8_t **data, int *size)
 {
     static const int extradata_nal_types_hevc[] = {
         HEVC_NAL_VPS, HEVC_NAL_SPS, HEVC_NAL_PPS,
     };
-    static const int extradata_nal_types_h264[] = {
-        H264_NAL_SPS, H264_NAL_PPS,
-    };
 
     ExtractExtradataContext *s = ctx->priv_data;
 
@@ -67,13 +110,8 @@ static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt,
     int nb_extradata_nal_types;
     int i, ret = 0;
 
-    if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) {
-        extradata_nal_types    = extradata_nal_types_hevc;
-        nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_hevc);
-    } else {
-        extradata_nal_types    = extradata_nal_types_h264;
-        nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_h264);
-    }
+    extradata_nal_types    = extradata_nal_types_hevc;
+    nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_hevc);
 
     ret = ff_h2645_packet_split(&h2645_pkt, pkt->data, pkt->size,
                                 ctx, 0, 0, ctx->par_in->codec_id, 1);
@@ -236,8 +274,8 @@ static const struct {
                    uint8_t **data, int *size);
 } extract_tab[] = {
     { AV_CODEC_ID_CAVS,       extract_extradata_mpeg4   },
-    { AV_CODEC_ID_H264,       extract_extradata_h2645   },
-    { AV_CODEC_ID_HEVC,       extract_extradata_h2645   },
+    { AV_CODEC_ID_H264,       extract_extradata_h264    },
+    { AV_CODEC_ID_HEVC,       extract_extradata_h265    },
     { AV_CODEC_ID_MPEG1VIDEO, extract_extradata_mpeg12  },
     { AV_CODEC_ID_MPEG2VIDEO, extract_extradata_mpeg12  },
     { AV_CODEC_ID_MPEG4,      extract_extradata_mpeg4   },
-- 
2.12.0



More information about the ffmpeg-devel mailing list