mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-21 10:55:51 +02:00
rtpdec_hevc: Parse out of band vps/sps/pps/sei from fmtp lines
These are assembled into extradata in the order vps/sps/pps/sei. Signed-off-by: Martin Storsjö <martin@martin.st>
This commit is contained in:
parent
557d4c4eca
commit
9b7f932ee5
@ -21,6 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libavutil/avstring.h"
|
#include "libavutil/avstring.h"
|
||||||
|
#include "libavutil/base64.h"
|
||||||
|
|
||||||
#include "avformat.h"
|
#include "avformat.h"
|
||||||
#include "rtpdec.h"
|
#include "rtpdec.h"
|
||||||
@ -34,6 +35,8 @@
|
|||||||
struct PayloadContext {
|
struct PayloadContext {
|
||||||
int using_donl_field;
|
int using_donl_field;
|
||||||
int profile_id;
|
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 };
|
static const uint8_t start_sequence[] = { 0x00, 0x00, 0x00, 0x01 };
|
||||||
@ -85,6 +88,65 @@ static av_cold int hevc_sdp_parse_fmtp_config(AVFormatContext *s,
|
|||||||
/* sprop-sps: [base64] */
|
/* sprop-sps: [base64] */
|
||||||
/* sprop-pps: [base64] */
|
/* sprop-pps: [base64] */
|
||||||
/* sprop-sei: [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 packet_size;
|
||||||
|
char *dst = base64packet;
|
||||||
|
|
||||||
|
while (*value && *value != ',' &&
|
||||||
|
(dst - base64packet) < sizeof(base64packet) - 1) {
|
||||||
|
*dst++ = *value++;
|
||||||
|
}
|
||||||
|
*dst++ = '\0';
|
||||||
|
|
||||||
|
if (*value == ',')
|
||||||
|
value++;
|
||||||
|
|
||||||
|
packet_size = av_base64_decode(decoded_packet, base64packet,
|
||||||
|
sizeof(decoded_packet));
|
||||||
|
if (packet_size > 0) {
|
||||||
|
uint8_t *dest = av_malloc(packet_size + sizeof(start_sequence) +
|
||||||
|
*size_ptr);
|
||||||
|
if (!dest) {
|
||||||
|
av_log(s, AV_LOG_ERROR,
|
||||||
|
"Unable to allocate memory for extradata!\n");
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
}
|
||||||
|
if (*size_ptr) {
|
||||||
|
memcpy(dest, *data_ptr, *size_ptr);
|
||||||
|
av_free(*data_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(dest + *size_ptr, start_sequence,
|
||||||
|
sizeof(start_sequence));
|
||||||
|
memcpy(dest + *size_ptr + sizeof(start_sequence),
|
||||||
|
decoded_packet, packet_size);
|
||||||
|
|
||||||
|
*data_ptr = dest;
|
||||||
|
*size_ptr += sizeof(start_sequence) + packet_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* max-lsr, max-lps, max-cpb, max-dpb, max-br, max-tr, max-tc */
|
/* max-lsr, max-lps, max-cpb, max-dpb, max-br, max-tr, max-tc */
|
||||||
/* max-fps */
|
/* max-fps */
|
||||||
|
|
||||||
@ -162,8 +224,41 @@ static av_cold int hevc_parse_sdp_line(AVFormatContext *ctx, int st_index,
|
|||||||
/* jump beyond the "-" and determine the height value */
|
/* jump beyond the "-" and determine the height value */
|
||||||
codec->height = atoi(sdp_line_ptr + 1);
|
codec->height = atoi(sdp_line_ptr + 1);
|
||||||
} else if (av_strstart(sdp_line_ptr, "fmtp:", &sdp_line_ptr)) {
|
} else if (av_strstart(sdp_line_ptr, "fmtp:", &sdp_line_ptr)) {
|
||||||
return ff_parse_fmtp(ctx, current_stream, hevc_data, sdp_line_ptr,
|
int ret = ff_parse_fmtp(ctx, current_stream, hevc_data, sdp_line_ptr,
|
||||||
hevc_sdp_parse_fmtp_config);
|
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;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user