diff mbox

[FFmpeg-devel] Support for h264/SVC over RTP and SVC base layer decoding in h264

Message ID 1509558649378.6548@harris.com
State New
Headers show

Commit Message

Breeden, Joshua Nov. 1, 2017, 5:49 p.m. UTC
> No but I wonder if the variables "y" and "t" can have more useful names
> (that may or may not make the comment unneeded),

I've made the variable names more self-explanatory and condensed the comments

> Please do not remove the empty line.

And fixed this as well.

Thanks,

Joshua Breeden

Comments

Michael Niedermayer Nov. 2, 2017, 11:36 p.m. UTC | #1
On Wed, Nov 01, 2017 at 05:49:48PM +0000, Breeden, Joshua wrote:
> > No but I wonder if the variables "y" and "t" can have more useful names
> > (that may or may not make the comment unneeded),
> 
> I've made the variable names more self-explanatory and condensed the comments
> 
> > Please do not remove the empty line.
> 
> And fixed this as well.
> 
> Thanks,
> 
> Joshua Breeden

>  h264.h       |    1 +
>  h264_parse.c |    6 ++++++
>  2 files changed, 7 insertions(+)
> b92e905eedab047e752f8e539f9bafff0e0dba09  0001-Parse-NAL-type-15-subset-SPS-in-H.264-extradata.patch
> From 65b33b5ed716712118d6cc9a9a0b3b6c260daa03 Mon Sep 17 00:00:00 2001
> From: Joshua Breeden <jbreeden@me.com>
> Date: Wed, 1 Nov 2017 13:27:20 -0400
> Subject: [PATCH 1/2] Parse NAL type 15 (subset SPS) in H.264 extradata

can you add a fate test for this ?

(i assume a test for rtp would be hard but if not, that would be
 welcome too)

thx

[...]
Breeden, Joshua Nov. 6, 2017, 5:52 p.m. UTC | #2
> can you add a fate test for this ?

I took a look around the existing tests to see how the existing extradata parsing is being tested, but didn't find anything. Is there something existing that I'm not seeing? If not, could you provide a little more guidance on how you'd like this tested? Since the modification uses an existing function without modification, I'd prefer to avoid reinventing the wheel if possible.

> (i assume a test for rtp would be hard but if not, that would be
 welcome too)

Yes, without RTP SVC packetization, which this patch does not provide, this would be quite difficult to accomplish.
diff mbox

Patch

From a592febfab5d5a7c534f6d21a42bf23289ff3ffa Mon Sep 17 00:00:00 2001
From: Joshua Breeden <jbreeden@me.com>
Date: Wed, 1 Nov 2017 13:39:54 -0400
Subject: [PATCH 2/2] Add support for non-interleaved H.264 SVC over RTP

---
 Changelog                    |  1 +
 libavformat/rtpdec.c         |  1 +
 libavformat/rtpdec_formats.h |  1 +
 libavformat/rtpdec_h264.c    | 79 +++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/Changelog b/Changelog
index 8c45b2946d..4e816bffd4 100644
--- a/Changelog
+++ b/Changelog
@@ -7,6 +7,7 @@  version <next>:
   requires 2.1 (or later) and pkg-config.
 - VDA dropped (use VideoToolbox instead)
 - MagicYUV encoder
+- RTP depacketization of non-interleaved H.264/SVC (RFC 6190)
 
 
 version 3.4:
diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c
index 4acb1ca629..1c5814749a 100644
--- a/libavformat/rtpdec.c
+++ b/libavformat/rtpdec.c
@@ -96,6 +96,7 @@  void ff_register_rtp_dynamic_payload_handlers(void)
     ff_register_dynamic_payload_handler(&ff_h263_2000_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_h263_rfc2190_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_h264_dynamic_handler);
+    ff_register_dynamic_payload_handler(&ff_h264_svc_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_hevc_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_ilbc_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_jpeg_dynamic_handler);
diff --git a/libavformat/rtpdec_formats.h b/libavformat/rtpdec_formats.h
index a436c9d62c..b67d1e338f 100644
--- a/libavformat/rtpdec_formats.h
+++ b/libavformat/rtpdec_formats.h
@@ -64,6 +64,7 @@  extern RTPDynamicProtocolHandler ff_h263_1998_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_h263_2000_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_h264_dynamic_handler;
+extern RTPDynamicProtocolHandler ff_h264_svc_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_hevc_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_ilbc_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_jpeg_dynamic_handler;
diff --git a/libavformat/rtpdec_h264.c b/libavformat/rtpdec_h264.c
index 6f8148ab6d..25b67f3571 100644
--- a/libavformat/rtpdec_h264.c
+++ b/libavformat/rtpdec_h264.c
@@ -308,6 +308,68 @@  static int h264_handle_packet_fu_a(AVFormatContext *ctx, PayloadContext *data, A
     return ff_h264_handle_frag_packet(pkt, buf, len, start_bit, &nal, 1);
 }
 
+static int h264_handle_packet_pacsi(AVFormatContext *ctx, PayloadContext *data, AVPacket *pkt,
+                                    const uint8_t *buf, int len,
+                                    int *nal_counters, int nal_mask)
+{
+    uint8_t *dst       = NULL;
+    const uint8_t *src = buf;
+    int src_len        = len;
+    int total_length   = 0;
+    int ret;
+    int tl0_pic_idx_bytes, donc_bytes;
+    int opt_offset;
+
+    if (len < 5)
+        return AVERROR_INVALIDDATA;
+
+    src     += 4;
+    src_len -= 4;
+
+    tl0_pic_idx_bytes = 3 * ((src[0] >> 6) & 1);
+    donc_bytes        = 2 * ((src[0] >> 5) & 1);
+
+    opt_offset = tl0_pic_idx_bytes + donc_bytes + 1;
+    src       += opt_offset;
+    src_len   -= opt_offset;
+
+    // calculate size of NALs plus start codes
+    while (src_len > 2) {
+        uint16_t nal_size = AV_RB16(src);
+
+        total_length += sizeof(start_sequence) + nal_size;
+        src          += 2 + nal_size;
+        src_len      -= 2 + nal_size;
+    }
+
+    // create packet to hold NALs
+    if ((ret = av_new_packet(pkt, total_length)) < 0)
+        return ret;
+    dst     = pkt->data;
+    src     = buf + 4 + opt_offset;
+    src_len = len - 4 - opt_offset;
+
+    // copy NALs with start codes
+    while (src_len > 2) {
+        uint16_t nal_size = AV_RB16(src);
+        src     += 2;
+        src_len -= 2;
+
+        memcpy(dst, start_sequence, sizeof(start_sequence));
+        dst += sizeof(start_sequence);
+        memcpy(dst, src, nal_size);
+        if (nal_counters)
+            nal_counters[(*src) & nal_mask]++;
+        dst += nal_size;
+
+        // eat what we handled
+        src     += nal_size;
+        src_len -= nal_size;
+    }
+
+    return 0;
+}
+
 // return 0 on packet, no more left, 1 on packet, 1 on partial packet
 static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data,
                               AVStream *st, AVPacket *pkt, uint32_t *timestamp,
@@ -360,7 +422,11 @@  static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data,
                                          NAL_COUNTERS, NAL_MASK);
         break;
 
-    case 30:                   // undefined
+    case 30:                   // PACSI (Annex G - SVC)
+        result = h264_handle_packet_pacsi(ctx, data, pkt, buf, len,
+                                          NAL_COUNTERS, NAL_MASK);
+        break;
+
     case 31:                   // undefined
     default:
         av_log(ctx, AV_LOG_ERROR, "Undefined type (%d)\n", type);
@@ -418,3 +484,14 @@  RTPDynamicProtocolHandler ff_h264_dynamic_handler = {
     .close            = h264_close_context,
     .parse_packet     = h264_handle_packet,
 };
+
+RTPDynamicProtocolHandler ff_h264_svc_dynamic_handler = {
+    .enc_name         = "H264-SVC",
+    .codec_type       = AVMEDIA_TYPE_VIDEO,
+    .codec_id         = AV_CODEC_ID_H264,
+    .need_parsing     = AVSTREAM_PARSE_FULL,
+    .priv_data_size   = sizeof(PayloadContext),
+    .parse_sdp_a_line = parse_h264_sdp_line,
+    .close            = h264_close_context,
+    .parse_packet     = h264_handle_packet,
+};
-- 
2.11.0