*/
#include "libavutil/avstring.h"
+#include "libavutil/base64.h"
#include "avformat.h"
#include "rtpdec.h"
struct PayloadContext {
int using_donl_field;
int profile_id;
+ uint8_t *sps, *pps, *vps, *sei;
+ int sps_size, pps_size, vps_size, sei_size;
};
static const uint8_t start_sequence[] = { 0x00, 0x00, 0x00, 0x01 };
/* sprop-sps: [base64] */
/* sprop-pps: [base64] */
/* 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;
+ if (!strcmp(attr, "sprop-vps")) {
+ data_ptr = &hevc_data->vps;
+ size_ptr = &hevc_data->vps_size;
+ } else if (!strcmp(attr, "sprop-sps")) {
+ data_ptr = &hevc_data->sps;
+ size_ptr = &hevc_data->sps_size;
+ } else if (!strcmp(attr, "sprop-pps")) {
+ data_ptr = &hevc_data->pps;
+ size_ptr = &hevc_data->pps_size;
+ } else if (!strcmp(attr, "sprop-sei")) {
+ data_ptr = &hevc_data->sei;
+ size_ptr = &hevc_data->sei_size;
+ }
+
+ 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;
+ }
+ }
+ }
+
/* max-lsr, max-lps, max-cpb, max-dpb, max-br, max-tr, max-tc */
/* max-fps */
/* jump beyond the "-" and determine the height value */
codec->height = atoi(sdp_line_ptr + 1);
} else if (av_strstart(sdp_line_ptr, "fmtp:", &sdp_line_ptr)) {
- return ff_parse_fmtp(ctx, current_stream, hevc_data, sdp_line_ptr,
- hevc_sdp_parse_fmtp_config);
+ int ret = ff_parse_fmtp(ctx, current_stream, hevc_data, sdp_line_ptr,
+ hevc_sdp_parse_fmtp_config);
+ if (hevc_data->vps_size || hevc_data->sps_size ||
+ hevc_data->pps_size || hevc_data->sei_size) {
+ av_freep(&codec->extradata);
+ codec->extradata_size = hevc_data->vps_size + hevc_data->sps_size +
+ hevc_data->pps_size + hevc_data->sei_size;
+ codec->extradata = av_malloc(codec->extradata_size +
+ FF_INPUT_BUFFER_PADDING_SIZE);
+ if (!codec->extradata) {
+ ret = AVERROR(ENOMEM);
+ codec->extradata_size = 0;
+ } else {
+ int pos = 0;
+ memcpy(codec->extradata + pos, hevc_data->vps, hevc_data->vps_size);
+ pos += hevc_data->vps_size;
+ memcpy(codec->extradata + pos, hevc_data->sps, hevc_data->sps_size);
+ pos += hevc_data->sps_size;
+ memcpy(codec->extradata + pos, hevc_data->pps, hevc_data->pps_size);
+ pos += hevc_data->pps_size;
+ memcpy(codec->extradata + pos, hevc_data->sei, hevc_data->sei_size);
+ pos += hevc_data->sei_size;
+ memset(codec->extradata + pos, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+ }
+
+ av_freep(&hevc_data->vps);
+ av_freep(&hevc_data->sps);
+ av_freep(&hevc_data->pps);
+ av_freep(&hevc_data->sei);
+ hevc_data->vps_size = 0;
+ hevc_data->sps_size = 0;
+ hevc_data->pps_size = 0;
+ hevc_data->sei_size = 0;
+ }
+ return ret;
}
return 0;
buf += RTP_HEVC_PAYLOAD_HEADER_SIZE;
len -= RTP_HEVC_PAYLOAD_HEADER_SIZE;
- if (len < 1)
- return AVERROR_INVALIDDATA;
/*
decode the FU header
av_dlog(ctx, " FU type %d with %d bytes\n", fu_type, len);
+ /* sanity check for size of input packet: 1 byte payload at least */
if (len > 0) {
new_nal_header[0] = (rtp_pl[0] & 0x81) | (fu_type << 1);
new_nal_header[1] = rtp_pl[1];
memcpy(pkt->data, buf, len);
}
} else {
- /* sanity check for size of input packet: 1 byte payload at least */
- av_log(ctx, AV_LOG_ERROR,
- "Too short RTP/HEVC packet, got %d bytes of NAL unit type %d\n",
- len, nal_type);
- res = AVERROR_INVALIDDATA;
+ if (len < 0) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Too short RTP/HEVC packet, got %d bytes of NAL unit type %d\n",
+ len, nal_type);
+ res = AVERROR_INVALIDDATA;
+ } else {
+ res = AVERROR(EAGAIN);
+ }
}
break;
}
RTPDynamicProtocolHandler ff_hevc_dynamic_handler = {
- .enc_name = "HEVC",
- .codec_type = AVMEDIA_TYPE_VIDEO,
- .codec_id = AV_CODEC_ID_HEVC,
- .init = hevc_init,
- .parse_sdp_a_line = hevc_parse_sdp_line,
- .alloc = hevc_new_context,
- .free = hevc_free_context,
- .parse_packet = hevc_handle_packet
-};
-
-RTPDynamicProtocolHandler ff_h265_dynamic_handler = {
.enc_name = "H265",
.codec_type = AVMEDIA_TYPE_VIDEO,
.codec_id = AV_CODEC_ID_HEVC,