[FFmpeg-devel] [PATCH 17/17] avformat/avc: Don't discard SPS extensions for some profiles

Andreas Rheinhardt andreas.rheinhardt at gmail.com
Thu Jul 9 22:20:22 EEST 2020


For some profiles, the AVCDecoderConfigurationRecord contains an array
containing all the SPS Extension NAL units; for the other profiles,
these NAL units should be put into the SPS array. Yet the latter hasn't
been done. This commit implements it.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at gmail.com>
---
Honestly, I have no sample containing an SPS extension, so this is
untested.
Btw: The spec is quiet on the order in the SPS array in this case.
Should it be all SPS first, then the extensions or should the it be that
an SPS is immediately followed by its extension (if present) followed by
the next SPS? All it says is that they should be placed in the SPS
array.

 libavformat/avc.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/libavformat/avc.c b/libavformat/avc.c
index 0f43b295a4..84a55fdc98 100644
--- a/libavformat/avc.c
+++ b/libavformat/avc.c
@@ -185,13 +185,13 @@ static void write_array(AVIOContext *pb, const uint8_t *const *ps,
 int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
 {
     const uint8_t *nal, *nal_end, *end;
-    int ret, nb_sps = 0, nb_pps = 0, nb_sps_ext = 0;
-    const uint8_t *sps[H264_MAX_SPS_COUNT];
+    int ret, nb_sps = 0, nb_pps = 0, nb_sps_ext = 0, ext_in_sps_array;
+    const uint8_t *sps[2 * H264_MAX_SPS_COUNT];
     const uint8_t *pps[H264_MAX_PPS_COUNT];
-    const uint8_t *sps_ext[H264_MAX_SPS_COUNT];
-    uint16_t sps_sizes[H264_MAX_SPS_COUNT]     = { 0 };
+    uint16_t sps_sizes[2 * H264_MAX_SPS_COUNT] = { 0 };
     uint16_t pps_sizes[H264_MAX_PPS_COUNT]     = { 0 };
-    uint16_t sps_ext_sizes[H264_MAX_SPS_COUNT] = { 0 };
+    const uint8_t **const sps_ext = &sps[H264_MAX_SPS_COUNT];
+    uint16_t *const sps_ext_sizes = &sps_sizes[H264_MAX_SPS_COUNT];
     H264SPS seq;
 
     if (len <= 6)
@@ -249,8 +249,14 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
         }
     }
 
-    if (!nb_sps || nb_sps == H264_MAX_SPS_COUNT ||
-        !nb_pps || nb_pps == H264_MAX_PPS_COUNT)
+    if (!nb_sps || !nb_pps)
+        return AVERROR_INVALIDDATA;
+    ext_in_sps_array = seq.profile_idc == 66 ||
+                       seq.profile_idc == 77 ||
+                       seq.profile_idc == 88;
+    if (ext_in_sps_array)
+        nb_sps += nb_sps_ext;
+    if (nb_sps >= H264_MAX_SPS_COUNT || nb_pps >= H264_MAX_PPS_COUNT)
         return AVERROR_INVALIDDATA;
 
     avio_w8(pb, 1); /* version */
@@ -258,10 +264,11 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
     avio_w8(pb, seq.constraint_set_flags); /* profile compat */
     avio_w8(pb, seq.level_idc);
     avio_w8(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */
-    write_array(pb, sps, sps_sizes, nb_sps, H264_MAX_SPS_COUNT, 0xe0);
+    write_array(pb, sps, sps_sizes, nb_sps,
+                H264_MAX_SPS_COUNT * (1 + ext_in_sps_array), 0xe0);
     write_array(pb, pps, pps_sizes, nb_pps, H264_MAX_PPS_COUNT, 0x00);
 
-    if (seq.profile_idc != 66 && seq.profile_idc != 77 && seq.profile_idc != 88) {
+    if (!ext_in_sps_array) {
         avio_w8(pb, 0xfc |  seq.chroma_format_idc); /* 6 bits reserved (111111) + chroma_format_idc */
         avio_w8(pb, 0xf8 | seq.bit_depth_luma_minus8); /* 5 bits reserved (11111) + bit_depth_luma_minus8 */
         avio_w8(pb, 0xf8 | seq.bit_depth_chroma_minus8); /* 5 bits reserved (11111) + bit_depth_chroma_minus8 */
-- 
2.20.1



More information about the ffmpeg-devel mailing list