#include "avformat.h"
#include "rtpdec.h"
+#include "rtpdec_formats.h"
#define RTP_HEVC_PAYLOAD_HEADER_SIZE 2
#define RTP_HEVC_FU_HEADER_SIZE 1
static const uint8_t start_sequence[] = { 0x00, 0x00, 0x00, 0x01 };
-static av_cold PayloadContext *hevc_new_context(void)
-{
- return av_mallocz(sizeof(PayloadContext));
-}
-
-static av_cold void hevc_free_context(PayloadContext *data)
-{
- av_free(data);
-}
-
-static av_cold int hevc_init(AVFormatContext *ctx, int st_index,
- PayloadContext *data)
-{
- av_dlog(ctx, "hevc_init() for stream %d\n", st_index);
-
- if (st_index < 0)
- return 0;
-
- ctx->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL;
-
- return 0;
-}
-
static av_cold int hevc_sdp_parse_fmtp_config(AVFormatContext *s,
AVStream *stream,
PayloadContext *hevc_data,
/* sprop-sei: [base64] */
if (!strcmp(attr, "sprop-vps") || !strcmp(attr, "sprop-sps") ||
!strcmp(attr, "sprop-pps") || !strcmp(attr, "sprop-sei")) {
- uint8_t **data_ptr;
- int *size_ptr;
+ uint8_t **data_ptr = NULL;
+ int *size_ptr = NULL;
if (!strcmp(attr, "sprop-vps")) {
data_ptr = &hevc_data->vps;
size_ptr = &hevc_data->vps_size;
} else
av_assert0(0);
- while (*value) {
- char base64packet[1024];
- uint8_t decoded_packet[1024];
- int decoded_packet_size;
- char *dst = base64packet;
-
- while (*value && *value != ',' &&
- (dst - base64packet) < sizeof(base64packet) - 1) {
- *dst++ = *value++;
- }
- *dst++ = '\0';
-
- if (*value == ',')
- value++;
-
- decoded_packet_size = av_base64_decode(decoded_packet, base64packet,
- sizeof(decoded_packet));
- if (decoded_packet_size > 0) {
- uint8_t *tmp = av_realloc(*data_ptr, decoded_packet_size +
- sizeof(start_sequence) + *size_ptr);
- if (!tmp) {
- av_log(s, AV_LOG_ERROR,
- "Unable to allocate memory for extradata!\n");
- return AVERROR(ENOMEM);
- }
- *data_ptr = tmp;
-
- memcpy(*data_ptr + *size_ptr, start_sequence,
- sizeof(start_sequence));
- memcpy(*data_ptr + *size_ptr + sizeof(start_sequence),
- decoded_packet, decoded_packet_size);
-
- *size_ptr += sizeof(start_sequence) + decoded_packet_size;
- }
- }
+ ff_h264_parse_sprop_parameter_sets(s, data_ptr,
+ size_ptr, value);
}
/* max-lsr, max-lps, max-cpb, max-dpb, max-br, max-tr, max-tc */
}
/*
- decode the HEVC payload header according to section 4 of draft version 6:
-
- 0 1
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- |F| Type | LayerId | TID |
- +-------------+-----------------+
-
- Forbidden zero (F): 1 bit
- NAL unit type (Type): 6 bits
- NUH layer ID (LayerId): 6 bits
- NUH temporal ID plus 1 (TID): 3 bits
- */
+ * decode the HEVC payload header according to section 4 of draft version 6:
+ *
+ * 0 1
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |F| Type | LayerId | TID |
+ * +-------------+-----------------+
+ *
+ * Forbidden zero (F): 1 bit
+ * NAL unit type (Type): 6 bits
+ * NUH layer ID (LayerId): 6 bits
+ * NUH temporal ID plus 1 (TID): 3 bits
+ */
nal_type = (buf[0] >> 1) & 0x3f;
lid = ((buf[0] << 5) & 0x20) | ((buf[1] >> 3) & 0x1f);
tid = buf[1] & 0x07;
len -= RTP_HEVC_DONL_FIELD_SIZE;
}
- /*
- * pass 0: determine overall size of the A/V packet
- * pass 1: create resulting A/V packet
- */
- {
- int pass = 0;
- int pkt_size = 0;
- uint8_t *pkt_data = 0;
-
- for (pass = 0; pass < 2; pass++) {
- const uint8_t *buf1 = buf;
- int len1 = len;
-
- while (len1 > RTP_HEVC_AP_NALU_LENGTH_FIELD_SIZE) {
- uint16_t nalu_size = AV_RB16(buf1);
-
- /* pass the NALU length field */
- buf1 += RTP_HEVC_AP_NALU_LENGTH_FIELD_SIZE;
- len1 -= RTP_HEVC_AP_NALU_LENGTH_FIELD_SIZE;
-
- if (nalu_size > 0 && nalu_size <= len1) {
- if (pass == 0) {
- pkt_size += sizeof(start_sequence) + nalu_size;
- } else {
- /* A/V packet: copy start sequence */
- memcpy(pkt_data, start_sequence, sizeof(start_sequence));
- /* A/V packet: copy NAL unit data */
- memcpy(pkt_data + sizeof(start_sequence), buf1, nalu_size);
- /* shift pointer beyond the current NAL unit */
- pkt_data += sizeof(start_sequence) + nalu_size;
- }
- }
-
- /* pass the current NAL unit */
- buf1 += nalu_size;
- len1 -= nalu_size;
-
- /* pass the HEVC DOND field */
- if (rtp_hevc_ctx->using_donl_field) {
- buf1 += RTP_HEVC_DOND_FIELD_SIZE;
- len1 -= RTP_HEVC_DOND_FIELD_SIZE;
- }
- }
-
- /* create A/V packet */
- if (pass == 0) {
- if ((res = av_new_packet(pkt, pkt_size)) < 0)
- return res;
-
- pkt_data = pkt->data;
- }
- }
- }
-
+ res = ff_h264_handle_aggregated_packet(ctx, rtp_hevc_ctx, pkt, buf, len,
+ rtp_hevc_ctx->using_donl_field ?
+ RTP_HEVC_DOND_FIELD_SIZE : 0,
+ NULL, 0);
+ if (res < 0)
+ return res;
break;
/* fragmentation unit (FU) */
case 49:
len -= RTP_HEVC_PAYLOAD_HEADER_SIZE;
/*
- decode the FU header
-
- 0 1 2 3 4 5 6 7
- +-+-+-+-+-+-+-+-+
- |S|E| FuType |
- +---------------+
-
- Start fragment (S): 1 bit
- End fragment (E): 1 bit
- FuType: 6 bits
- */
+ * decode the FU header
+ *
+ * 0 1 2 3 4 5 6 7
+ * +-+-+-+-+-+-+-+-+
+ * |S|E| FuType |
+ * +---------------+
+ *
+ * Start fragment (S): 1 bit
+ * End fragment (E): 1 bit
+ * FuType: 6 bits
+ */
first_fragment = buf[0] & 0x80;
last_fragment = buf[0] & 0x40;
fu_type = buf[0] & 0x3f;
.enc_name = "H265",
.codec_type = AVMEDIA_TYPE_VIDEO,
.codec_id = AV_CODEC_ID_HEVC,
- .init = hevc_init,
+ .need_parsing = AVSTREAM_PARSE_FULL,
+ .priv_data_size = sizeof(PayloadContext),
.parse_sdp_a_line = hevc_parse_sdp_line,
- .alloc = hevc_new_context,
- .free = hevc_free_context,
- .parse_packet = hevc_handle_packet
+ .parse_packet = hevc_handle_packet,
};