You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-10 06:10:52 +02:00
lavf/sdp: add more thorough error handling
Return error codes when constructing a stream config fails, rather than just disregarding the failure and continuing. Propagate the error codes from av_sdp_create().
This commit is contained in:
@@ -556,10 +556,11 @@ uint64_t ff_parse_ntp_time(uint64_t ntp_ts);
|
|||||||
* @param ttl the time to live of the stream, 0 if not multicast
|
* @param ttl the time to live of the stream, 0 if not multicast
|
||||||
* @param fmt the AVFormatContext, which might contain options modifying
|
* @param fmt the AVFormatContext, which might contain options modifying
|
||||||
* the generated SDP
|
* the generated SDP
|
||||||
|
* @return 0 on success, a negative error code on failure
|
||||||
*/
|
*/
|
||||||
void ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx,
|
int ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx,
|
||||||
const char *dest_addr, const char *dest_type,
|
const char *dest_addr, const char *dest_type,
|
||||||
int port, int ttl, AVFormatContext *fmt);
|
int port, int ttl, AVFormatContext *fmt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a packet to another muxer than the one the user originally
|
* Write a packet to another muxer than the one the user originally
|
||||||
|
@@ -151,7 +151,8 @@ static int sdp_get_address(char *dest_addr, int size, int *ttl, const char *url)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_PSET_SIZE 1024
|
#define MAX_PSET_SIZE 1024
|
||||||
static char *extradata2psets(AVFormatContext *s, const AVCodecParameters *par)
|
static int extradata2psets(AVFormatContext *s, const AVCodecParameters *par,
|
||||||
|
char **out)
|
||||||
{
|
{
|
||||||
char *psets, *p;
|
char *psets, *p;
|
||||||
const uint8_t *r;
|
const uint8_t *r;
|
||||||
@@ -162,15 +163,18 @@ static char *extradata2psets(AVFormatContext *s, const AVCodecParameters *par)
|
|||||||
uint8_t *tmpbuf = NULL;
|
uint8_t *tmpbuf = NULL;
|
||||||
const uint8_t *sps = NULL, *sps_end;
|
const uint8_t *sps = NULL, *sps_end;
|
||||||
|
|
||||||
|
*out = NULL;
|
||||||
|
|
||||||
if (par->extradata_size > MAX_EXTRADATA_SIZE) {
|
if (par->extradata_size > MAX_EXTRADATA_SIZE) {
|
||||||
av_log(s, AV_LOG_ERROR, "Too much extradata!\n");
|
av_log(s, AV_LOG_ERROR, "Too much extradata!\n");
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
if (par->extradata[0] == 1) {
|
if (par->extradata[0] == 1) {
|
||||||
if (ff_avc_write_annexb_extradata(par->extradata, &extradata,
|
int ret = ff_avc_write_annexb_extradata(par->extradata, &extradata,
|
||||||
&extradata_size))
|
&extradata_size);
|
||||||
return NULL;
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
tmpbuf = extradata;
|
tmpbuf = extradata;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +182,7 @@ static char *extradata2psets(AVFormatContext *s, const AVCodecParameters *par)
|
|||||||
if (!psets) {
|
if (!psets) {
|
||||||
av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the parameter sets.\n");
|
av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the parameter sets.\n");
|
||||||
av_free(tmpbuf);
|
av_free(tmpbuf);
|
||||||
return NULL;
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
memcpy(psets, pset_string, strlen(pset_string));
|
memcpy(psets, pset_string, strlen(pset_string));
|
||||||
p = psets + strlen(pset_string);
|
p = psets + strlen(pset_string);
|
||||||
@@ -203,11 +207,12 @@ static char *extradata2psets(AVFormatContext *s, const AVCodecParameters *par)
|
|||||||
sps_end = r1;
|
sps_end = r1;
|
||||||
}
|
}
|
||||||
if (!av_base64_encode(p, MAX_PSET_SIZE - (p - psets), r, r1 - r)) {
|
if (!av_base64_encode(p, MAX_PSET_SIZE - (p - psets), r, r1 - r)) {
|
||||||
av_log(s, AV_LOG_ERROR, "Cannot Base64-encode %"PTRDIFF_SPECIFIER" %"PTRDIFF_SPECIFIER"!\n", MAX_PSET_SIZE - (p - psets), r1 - r);
|
av_log(s, AV_LOG_ERROR, "Cannot Base64-encode %"PTRDIFF_SPECIFIER" %"PTRDIFF_SPECIFIER"!\n",
|
||||||
|
MAX_PSET_SIZE - (p - psets), r1 - r);
|
||||||
av_free(psets);
|
av_free(psets);
|
||||||
av_free(tmpbuf);
|
av_free(tmpbuf);
|
||||||
|
|
||||||
return NULL;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
p += strlen(p);
|
p += strlen(p);
|
||||||
r = r1;
|
r = r1;
|
||||||
@@ -219,10 +224,11 @@ static char *extradata2psets(AVFormatContext *s, const AVCodecParameters *par)
|
|||||||
}
|
}
|
||||||
av_free(tmpbuf);
|
av_free(tmpbuf);
|
||||||
|
|
||||||
return psets;
|
*out = psets;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *extradata2psets_hevc(const AVCodecParameters *par)
|
static int extradata2psets_hevc(const AVCodecParameters *par, char **out)
|
||||||
{
|
{
|
||||||
char *psets;
|
char *psets;
|
||||||
uint8_t *extradata = par->extradata;
|
uint8_t *extradata = par->extradata;
|
||||||
@@ -231,7 +237,9 @@ static char *extradata2psets_hevc(const AVCodecParameters *par)
|
|||||||
int ps_pos[3] = { 0 };
|
int ps_pos[3] = { 0 };
|
||||||
static const char * const ps_names[3] = { "vps", "sps", "pps" };
|
static const char * const ps_names[3] = { "vps", "sps", "pps" };
|
||||||
int num_arrays, num_nalus;
|
int num_arrays, num_nalus;
|
||||||
int pos, i, j;
|
int pos, i, j, ret;
|
||||||
|
|
||||||
|
*out = NULL;
|
||||||
|
|
||||||
// Convert to hvcc format. Since we need to group multiple NALUs of
|
// Convert to hvcc format. Since we need to group multiple NALUs of
|
||||||
// the same type, and we might need to convert from one format to the
|
// the same type, and we might need to convert from one format to the
|
||||||
@@ -239,9 +247,13 @@ static char *extradata2psets_hevc(const AVCodecParameters *par)
|
|||||||
// format.
|
// format.
|
||||||
if (par->extradata[0] != 1) {
|
if (par->extradata[0] != 1) {
|
||||||
AVIOContext *pb;
|
AVIOContext *pb;
|
||||||
if (avio_open_dyn_buf(&pb) < 0)
|
|
||||||
return NULL;
|
ret = avio_open_dyn_buf(&pb);
|
||||||
if (ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0) < 0) {
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0);
|
||||||
|
if (ret < 0) {
|
||||||
avio_close_dyn_buf(pb, &tmpbuf);
|
avio_close_dyn_buf(pb, &tmpbuf);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -284,8 +296,11 @@ static char *extradata2psets_hevc(const AVCodecParameters *par)
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
psets = av_mallocz(MAX_PSET_SIZE);
|
psets = av_mallocz(MAX_PSET_SIZE);
|
||||||
if (!psets)
|
if (!psets) {
|
||||||
|
ret = AVERROR(ENOMEM);
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
psets[0] = '\0';
|
psets[0] = '\0';
|
||||||
|
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
@@ -316,40 +331,48 @@ static char *extradata2psets_hevc(const AVCodecParameters *par)
|
|||||||
}
|
}
|
||||||
av_free(tmpbuf);
|
av_free(tmpbuf);
|
||||||
|
|
||||||
return psets;
|
*out = psets;
|
||||||
|
return 0;
|
||||||
err:
|
err:
|
||||||
|
if (ret >= 0)
|
||||||
|
ret = AVERROR_INVALIDDATA;
|
||||||
av_free(tmpbuf);
|
av_free(tmpbuf);
|
||||||
return NULL;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *extradata2config(AVFormatContext *s, const AVCodecParameters *par)
|
static int extradata2config(AVFormatContext *s, const AVCodecParameters *par,
|
||||||
|
char **out)
|
||||||
{
|
{
|
||||||
char *config;
|
char *config;
|
||||||
|
|
||||||
|
*out = NULL;
|
||||||
|
|
||||||
if (par->extradata_size > MAX_EXTRADATA_SIZE) {
|
if (par->extradata_size > MAX_EXTRADATA_SIZE) {
|
||||||
av_log(s, AV_LOG_ERROR, "Too much extradata!\n");
|
av_log(s, AV_LOG_ERROR, "Too much extradata!\n");
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
config = av_malloc(10 + par->extradata_size * 2);
|
config = av_malloc(10 + par->extradata_size * 2);
|
||||||
if (!config) {
|
if (!config) {
|
||||||
av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n");
|
av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n");
|
||||||
return NULL;
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
memcpy(config, "; config=", 9);
|
memcpy(config, "; config=", 9);
|
||||||
ff_data_to_hex(config + 9, par->extradata, par->extradata_size, 0);
|
ff_data_to_hex(config + 9, par->extradata, par->extradata_size, 0);
|
||||||
|
|
||||||
return config;
|
*out = config;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *xiph_extradata2config(AVFormatContext *s, const AVCodecParameters *par)
|
static int xiph_extradata2config(AVFormatContext *s, const AVCodecParameters *par,
|
||||||
|
char **out)
|
||||||
{
|
{
|
||||||
uint8_t *config;
|
uint8_t *config;
|
||||||
char *encoded_config;
|
char *encoded_config;
|
||||||
const uint8_t *header_start[3];
|
const uint8_t *header_start[3];
|
||||||
int headers_len, header_len[3], config_len;
|
int headers_len, header_len[3], config_len;
|
||||||
int first_header_size;
|
int first_header_size, ret;
|
||||||
|
|
||||||
|
*out = NULL;
|
||||||
|
|
||||||
switch (par->codec_id) {
|
switch (par->codec_id) {
|
||||||
case AV_CODEC_ID_THEORA:
|
case AV_CODEC_ID_THEORA:
|
||||||
@@ -360,14 +383,15 @@ static char *xiph_extradata2config(AVFormatContext *s, const AVCodecParameters *
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
av_log(s, AV_LOG_ERROR, "Unsupported Xiph codec ID\n");
|
av_log(s, AV_LOG_ERROR, "Unsupported Xiph codec ID\n");
|
||||||
return NULL;
|
return AVERROR(ENOSYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (avpriv_split_xiph_headers(par->extradata, par->extradata_size,
|
ret = avpriv_split_xiph_headers(par->extradata, par->extradata_size,
|
||||||
first_header_size, header_start,
|
first_header_size, header_start,
|
||||||
header_len) < 0) {
|
header_len);
|
||||||
|
if (ret < 0) {
|
||||||
av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n");
|
av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n");
|
||||||
return NULL;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
headers_len = header_len[0] + header_len[2];
|
headers_len = header_len[0] + header_len[2];
|
||||||
@@ -405,12 +429,13 @@ static char *xiph_extradata2config(AVFormatContext *s, const AVCodecParameters *
|
|||||||
config, config_len);
|
config, config_len);
|
||||||
av_free(config);
|
av_free(config);
|
||||||
|
|
||||||
return encoded_config;
|
*out = encoded_config;
|
||||||
|
return 0;
|
||||||
|
|
||||||
xiph_fail:
|
xiph_fail:
|
||||||
av_log(s, AV_LOG_ERROR,
|
av_log(s, AV_LOG_ERROR,
|
||||||
"Not enough memory for configuration string\n");
|
"Not enough memory for configuration string\n");
|
||||||
return NULL;
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int latm_context2profilelevel(const AVCodecParameters *par)
|
static int latm_context2profilelevel(const AVCodecParameters *par)
|
||||||
@@ -442,7 +467,8 @@ static int latm_context2profilelevel(const AVCodecParameters *par)
|
|||||||
return profile_level;
|
return profile_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *latm_context2config(AVFormatContext *s, const AVCodecParameters *par)
|
static int latm_context2config(AVFormatContext *s, const AVCodecParameters *par,
|
||||||
|
char **out)
|
||||||
{
|
{
|
||||||
/* MP4A-LATM
|
/* MP4A-LATM
|
||||||
* The RTP payload format specification is described in RFC 3016
|
* The RTP payload format specification is described in RFC 3016
|
||||||
@@ -452,12 +478,14 @@ static char *latm_context2config(AVFormatContext *s, const AVCodecParameters *pa
|
|||||||
int rate_index;
|
int rate_index;
|
||||||
char *config;
|
char *config;
|
||||||
|
|
||||||
|
*out = NULL;
|
||||||
|
|
||||||
for (rate_index = 0; rate_index < 16; rate_index++)
|
for (rate_index = 0; rate_index < 16; rate_index++)
|
||||||
if (avpriv_mpeg4audio_sample_rates[rate_index] == par->sample_rate)
|
if (avpriv_mpeg4audio_sample_rates[rate_index] == par->sample_rate)
|
||||||
break;
|
break;
|
||||||
if (rate_index == 16) {
|
if (rate_index == 16) {
|
||||||
av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n");
|
av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n");
|
||||||
return NULL;
|
return AVERROR(ENOSYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
config_byte[0] = 0x40;
|
config_byte[0] = 0x40;
|
||||||
@@ -470,18 +498,20 @@ static char *latm_context2config(AVFormatContext *s, const AVCodecParameters *pa
|
|||||||
config = av_malloc(6*2+1);
|
config = av_malloc(6*2+1);
|
||||||
if (!config) {
|
if (!config) {
|
||||||
av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n");
|
av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n");
|
||||||
return NULL;
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
ff_data_to_hex(config, config_byte, 6, 1);
|
ff_data_to_hex(config, config_byte, 6, 1);
|
||||||
|
|
||||||
return config;
|
*out = config;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st,
|
static int sdp_write_media_attributes(char *buff, int size, const AVStream *st,
|
||||||
int payload_type, AVFormatContext *fmt)
|
int payload_type, AVFormatContext *fmt)
|
||||||
{
|
{
|
||||||
char *config = NULL;
|
char *config = NULL;
|
||||||
const AVCodecParameters *p = st->codecpar;
|
const AVCodecParameters *p = st->codecpar;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
switch (p->codec_id) {
|
switch (p->codec_id) {
|
||||||
case AV_CODEC_ID_DIRAC:
|
case AV_CODEC_ID_DIRAC:
|
||||||
@@ -493,7 +523,9 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st
|
|||||||
av_opt_flag_is_set(fmt->priv_data, "rtpflags", "h264_mode0"))
|
av_opt_flag_is_set(fmt->priv_data, "rtpflags", "h264_mode0"))
|
||||||
mode = 0;
|
mode = 0;
|
||||||
if (p->extradata_size) {
|
if (p->extradata_size) {
|
||||||
config = extradata2psets(fmt, p);
|
ret = extradata2psets(fmt, p, &config);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
av_strlcatf(buff, size, "a=rtpmap:%d H264/90000\r\n"
|
av_strlcatf(buff, size, "a=rtpmap:%d H264/90000\r\n"
|
||||||
"a=fmtp:%d packetization-mode=%d%s\r\n",
|
"a=fmtp:%d packetization-mode=%d%s\r\n",
|
||||||
@@ -530,8 +562,11 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st
|
|||||||
payload_type, p->width, p->height);
|
payload_type, p->width, p->height);
|
||||||
break;
|
break;
|
||||||
case AV_CODEC_ID_HEVC:
|
case AV_CODEC_ID_HEVC:
|
||||||
if (p->extradata_size)
|
if (p->extradata_size) {
|
||||||
config = extradata2psets_hevc(p);
|
ret = extradata2psets_hevc(p, &config);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
av_strlcatf(buff, size, "a=rtpmap:%d H265/90000\r\n", payload_type);
|
av_strlcatf(buff, size, "a=rtpmap:%d H265/90000\r\n", payload_type);
|
||||||
if (config)
|
if (config)
|
||||||
av_strlcatf(buff, size, "a=fmtp:%d %s\r\n",
|
av_strlcatf(buff, size, "a=fmtp:%d %s\r\n",
|
||||||
@@ -539,7 +574,9 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st
|
|||||||
break;
|
break;
|
||||||
case AV_CODEC_ID_MPEG4:
|
case AV_CODEC_ID_MPEG4:
|
||||||
if (p->extradata_size) {
|
if (p->extradata_size) {
|
||||||
config = extradata2config(fmt, p);
|
ret = extradata2config(fmt, p, &config);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
av_strlcatf(buff, size, "a=rtpmap:%d MP4V-ES/90000\r\n"
|
av_strlcatf(buff, size, "a=rtpmap:%d MP4V-ES/90000\r\n"
|
||||||
"a=fmtp:%d profile-level-id=1%s\r\n",
|
"a=fmtp:%d profile-level-id=1%s\r\n",
|
||||||
@@ -549,25 +586,24 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st
|
|||||||
case AV_CODEC_ID_AAC:
|
case AV_CODEC_ID_AAC:
|
||||||
if (fmt && fmt->oformat && fmt->oformat->priv_class &&
|
if (fmt && fmt->oformat && fmt->oformat->priv_class &&
|
||||||
av_opt_flag_is_set(fmt->priv_data, "rtpflags", "latm")) {
|
av_opt_flag_is_set(fmt->priv_data, "rtpflags", "latm")) {
|
||||||
config = latm_context2config(fmt, p);
|
ret = latm_context2config(fmt, p, &config);
|
||||||
if (!config)
|
if (ret < 0)
|
||||||
return NULL;
|
return ret;
|
||||||
av_strlcatf(buff, size, "a=rtpmap:%d MP4A-LATM/%d/%d\r\n"
|
av_strlcatf(buff, size, "a=rtpmap:%d MP4A-LATM/%d/%d\r\n"
|
||||||
"a=fmtp:%d profile-level-id=%d;cpresent=0;config=%s\r\n",
|
"a=fmtp:%d profile-level-id=%d;cpresent=0;config=%s\r\n",
|
||||||
payload_type, p->sample_rate, p->channels,
|
payload_type, p->sample_rate, p->channels,
|
||||||
payload_type, latm_context2profilelevel(p), config);
|
payload_type, latm_context2profilelevel(p), config);
|
||||||
} else {
|
} else {
|
||||||
if (p->extradata_size) {
|
if (p->extradata_size) {
|
||||||
config = extradata2config(fmt, p);
|
ret = extradata2config(fmt, p, &config);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
/* FIXME: maybe we can forge config information based on the
|
/* FIXME: maybe we can forge config information based on the
|
||||||
* codec parameters...
|
* codec parameters...
|
||||||
*/
|
*/
|
||||||
av_log(fmt, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n");
|
av_log(fmt, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n");
|
||||||
return NULL;
|
return AVERROR(ENOSYS);
|
||||||
}
|
|
||||||
if (!config) {
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n"
|
av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n"
|
||||||
"a=fmtp:%d profile-level-id=1;"
|
"a=fmtp:%d profile-level-id=1;"
|
||||||
@@ -615,11 +651,13 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st
|
|||||||
break;
|
break;
|
||||||
case AV_CODEC_ID_VORBIS:
|
case AV_CODEC_ID_VORBIS:
|
||||||
if (p->extradata_size)
|
if (p->extradata_size)
|
||||||
config = xiph_extradata2config(fmt, p);
|
ret = xiph_extradata2config(fmt, p, &config);
|
||||||
else
|
else {
|
||||||
av_log(fmt, AV_LOG_ERROR, "Vorbis configuration info missing\n");
|
av_log(fmt, AV_LOG_ERROR, "Vorbis configuration info missing\n");
|
||||||
if (!config)
|
ret = AVERROR_INVALIDDATA;
|
||||||
return NULL;
|
}
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
av_strlcatf(buff, size, "a=rtpmap:%d vorbis/%d/%d\r\n"
|
av_strlcatf(buff, size, "a=rtpmap:%d vorbis/%d/%d\r\n"
|
||||||
"a=fmtp:%d configuration=%s\r\n",
|
"a=fmtp:%d configuration=%s\r\n",
|
||||||
@@ -640,15 +678,17 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n");
|
av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n");
|
||||||
return NULL;
|
return AVERROR(ENOSYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->extradata_size)
|
if (p->extradata_size)
|
||||||
config = xiph_extradata2config(fmt, p);
|
ret = xiph_extradata2config(fmt, p, &config);
|
||||||
else
|
else {
|
||||||
av_log(fmt, AV_LOG_ERROR, "Theora configuration info missing\n");
|
av_log(fmt, AV_LOG_ERROR, "Theora configuration info missing\n");
|
||||||
if (!config)
|
ret = AVERROR_INVALIDDATA;
|
||||||
return NULL;
|
}
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
av_strlcatf(buff, size, "a=rtpmap:%d theora/90000\r\n"
|
av_strlcatf(buff, size, "a=rtpmap:%d theora/90000\r\n"
|
||||||
"a=fmtp:%d delivery-method=inline; "
|
"a=fmtp:%d delivery-method=inline; "
|
||||||
@@ -682,7 +722,7 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n");
|
av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n");
|
||||||
return NULL;
|
return AVERROR(ENOSYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
av_strlcatf(buff, size, "a=rtpmap:%d raw/90000\r\n"
|
av_strlcatf(buff, size, "a=rtpmap:%d raw/90000\r\n"
|
||||||
@@ -760,12 +800,12 @@ static char *sdp_write_media_attributes(char *buff, int size, const AVStream *st
|
|||||||
|
|
||||||
av_free(config);
|
av_free(config);
|
||||||
|
|
||||||
return buff;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx,
|
int ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx,
|
||||||
const char *dest_addr, const char *dest_type,
|
const char *dest_addr, const char *dest_type,
|
||||||
int port, int ttl, AVFormatContext *fmt)
|
int port, int ttl, AVFormatContext *fmt)
|
||||||
{
|
{
|
||||||
const AVCodecParameters *p = st->codecpar;
|
const AVCodecParameters *p = st->codecpar;
|
||||||
const char *type;
|
const char *type;
|
||||||
@@ -786,7 +826,7 @@ void ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx,
|
|||||||
av_strlcatf(buff, size, "b=AS:%"PRId64"\r\n", p->bit_rate / 1000);
|
av_strlcatf(buff, size, "b=AS:%"PRId64"\r\n", p->bit_rate / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
sdp_write_media_attributes(buff, size, st, payload_type, fmt);
|
return sdp_write_media_attributes(buff, size, st, payload_type, fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
|
int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
|
||||||
@@ -832,10 +872,13 @@ int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
|
|||||||
ttl = 0;
|
ttl = 0;
|
||||||
}
|
}
|
||||||
for (j = 0; j < ac[i]->nb_streams; j++) {
|
for (j = 0; j < ac[i]->nb_streams; j++) {
|
||||||
ff_sdp_write_media(buf, size, ac[i]->streams[j], index++,
|
int ret = ff_sdp_write_media(buf, size, ac[i]->streams[j], index++,
|
||||||
dst[0] ? dst : NULL, dst_type,
|
dst[0] ? dst : NULL, dst_type,
|
||||||
(port > 0) ? port + j * 2 : 0,
|
(port > 0) ? port + j * 2 : 0,
|
||||||
ttl, ac[i]);
|
ttl, ac[i]);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (port <= 0) {
|
if (port <= 0) {
|
||||||
av_strlcatf(buf, size,
|
av_strlcatf(buf, size,
|
||||||
"a=control:streamid=%d\r\n", i + j);
|
"a=control:streamid=%d\r\n", i + j);
|
||||||
@@ -864,9 +907,10 @@ int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
|
|||||||
return AVERROR(ENOSYS);
|
return AVERROR(ENOSYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx,
|
int ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx,
|
||||||
const char *dest_addr, const char *dest_type,
|
const char *dest_addr, const char *dest_type,
|
||||||
int port, int ttl, AVFormatContext *fmt)
|
int port, int ttl, AVFormatContext *fmt)
|
||||||
{
|
{
|
||||||
|
return AVERROR(ENOSYS);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user