1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * copyright (c) 2007 Luca Abeni 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * This file is part of FFmpeg. 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14cabdff1aSopenharmony_ci * Lesser General Public License for more details. 15cabdff1aSopenharmony_ci * 16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19cabdff1aSopenharmony_ci */ 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci#include "config_components.h" 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include <string.h> 24cabdff1aSopenharmony_ci#include "libavutil/avstring.h" 25cabdff1aSopenharmony_ci#include "libavutil/base64.h" 26cabdff1aSopenharmony_ci#include "libavutil/dict.h" 27cabdff1aSopenharmony_ci#include "libavutil/parseutils.h" 28cabdff1aSopenharmony_ci#include "libavutil/opt.h" 29cabdff1aSopenharmony_ci#include "libavcodec/xiph.h" 30cabdff1aSopenharmony_ci#include "libavcodec/mpeg4audio.h" 31cabdff1aSopenharmony_ci#include "avformat.h" 32cabdff1aSopenharmony_ci#include "internal.h" 33cabdff1aSopenharmony_ci#include "avc.h" 34cabdff1aSopenharmony_ci#include "hevc.h" 35cabdff1aSopenharmony_ci#include "rtp.h" 36cabdff1aSopenharmony_ci#if CONFIG_NETWORK 37cabdff1aSopenharmony_ci#include "network.h" 38cabdff1aSopenharmony_ci#endif 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_ci#if CONFIG_RTP_MUXER 41cabdff1aSopenharmony_ci#define MAX_EXTRADATA_SIZE ((INT_MAX - 10) / 2) 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_cistruct sdp_session_level { 44cabdff1aSopenharmony_ci int sdp_version; /**< protocol version (currently 0) */ 45cabdff1aSopenharmony_ci int id; /**< session ID */ 46cabdff1aSopenharmony_ci int version; /**< session version */ 47cabdff1aSopenharmony_ci int start_time; /**< session start time (NTP time, in seconds), 48cabdff1aSopenharmony_ci or 0 in case of permanent session */ 49cabdff1aSopenharmony_ci int end_time; /**< session end time (NTP time, in seconds), 50cabdff1aSopenharmony_ci or 0 if the session is not bounded */ 51cabdff1aSopenharmony_ci int ttl; /**< TTL, in case of multicast stream */ 52cabdff1aSopenharmony_ci const char *user; /**< username of the session's creator */ 53cabdff1aSopenharmony_ci const char *src_addr; /**< IP address of the machine from which the session was created */ 54cabdff1aSopenharmony_ci const char *src_type; /**< address type of src_addr */ 55cabdff1aSopenharmony_ci const char *dst_addr; /**< destination IP address (can be multicast) */ 56cabdff1aSopenharmony_ci const char *dst_type; /**< destination IP address type */ 57cabdff1aSopenharmony_ci const char *name; /**< session name (can be an empty string) */ 58cabdff1aSopenharmony_ci}; 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_cistatic void sdp_write_address(char *buff, int size, const char *dest_addr, 61cabdff1aSopenharmony_ci const char *dest_type, int ttl) 62cabdff1aSopenharmony_ci{ 63cabdff1aSopenharmony_ci if (dest_addr) { 64cabdff1aSopenharmony_ci if (!dest_type) 65cabdff1aSopenharmony_ci dest_type = "IP4"; 66cabdff1aSopenharmony_ci if (ttl > 0 && !strcmp(dest_type, "IP4")) { 67cabdff1aSopenharmony_ci /* The TTL should only be specified for IPv4 multicast addresses, 68cabdff1aSopenharmony_ci * not for IPv6. */ 69cabdff1aSopenharmony_ci av_strlcatf(buff, size, "c=IN %s %s/%d\r\n", dest_type, dest_addr, ttl); 70cabdff1aSopenharmony_ci } else { 71cabdff1aSopenharmony_ci av_strlcatf(buff, size, "c=IN %s %s\r\n", dest_type, dest_addr); 72cabdff1aSopenharmony_ci } 73cabdff1aSopenharmony_ci } 74cabdff1aSopenharmony_ci} 75cabdff1aSopenharmony_ci 76cabdff1aSopenharmony_cistatic void sdp_write_header(char *buff, int size, struct sdp_session_level *s) 77cabdff1aSopenharmony_ci{ 78cabdff1aSopenharmony_ci av_strlcatf(buff, size, "v=%d\r\n" 79cabdff1aSopenharmony_ci "o=- %d %d IN %s %s\r\n" 80cabdff1aSopenharmony_ci "s=%s\r\n", 81cabdff1aSopenharmony_ci s->sdp_version, 82cabdff1aSopenharmony_ci s->id, s->version, s->src_type, s->src_addr, 83cabdff1aSopenharmony_ci s->name); 84cabdff1aSopenharmony_ci sdp_write_address(buff, size, s->dst_addr, s->dst_type, s->ttl); 85cabdff1aSopenharmony_ci av_strlcatf(buff, size, "t=%d %d\r\n" 86cabdff1aSopenharmony_ci "a=tool:libavformat " AV_STRINGIFY(LIBAVFORMAT_VERSION) "\r\n", 87cabdff1aSopenharmony_ci s->start_time, s->end_time); 88cabdff1aSopenharmony_ci} 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_ci#if CONFIG_NETWORK 91cabdff1aSopenharmony_cistatic int resolve_destination(char *dest_addr, int size, char *type, 92cabdff1aSopenharmony_ci int type_size) 93cabdff1aSopenharmony_ci{ 94cabdff1aSopenharmony_ci struct addrinfo hints = { 0 }, *ai; 95cabdff1aSopenharmony_ci int is_multicast; 96cabdff1aSopenharmony_ci 97cabdff1aSopenharmony_ci av_strlcpy(type, "IP4", type_size); 98cabdff1aSopenharmony_ci if (!dest_addr[0]) 99cabdff1aSopenharmony_ci return 0; 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_ci /* Resolve the destination, since it must be written 102cabdff1aSopenharmony_ci * as a numeric IP address in the SDP. */ 103cabdff1aSopenharmony_ci 104cabdff1aSopenharmony_ci if (getaddrinfo(dest_addr, NULL, &hints, &ai)) 105cabdff1aSopenharmony_ci return 0; 106cabdff1aSopenharmony_ci getnameinfo(ai->ai_addr, ai->ai_addrlen, dest_addr, size, 107cabdff1aSopenharmony_ci NULL, 0, NI_NUMERICHOST); 108cabdff1aSopenharmony_ci#ifdef AF_INET6 109cabdff1aSopenharmony_ci if (ai->ai_family == AF_INET6) 110cabdff1aSopenharmony_ci av_strlcpy(type, "IP6", type_size); 111cabdff1aSopenharmony_ci#endif 112cabdff1aSopenharmony_ci is_multicast = ff_is_multicast_address(ai->ai_addr); 113cabdff1aSopenharmony_ci freeaddrinfo(ai); 114cabdff1aSopenharmony_ci return is_multicast; 115cabdff1aSopenharmony_ci} 116cabdff1aSopenharmony_ci#else 117cabdff1aSopenharmony_cistatic int resolve_destination(char *dest_addr, int size, char *type, 118cabdff1aSopenharmony_ci int type_size) 119cabdff1aSopenharmony_ci{ 120cabdff1aSopenharmony_ci return 0; 121cabdff1aSopenharmony_ci} 122cabdff1aSopenharmony_ci#endif 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_cistatic int sdp_get_address(char *dest_addr, int size, int *ttl, const char *url) 125cabdff1aSopenharmony_ci{ 126cabdff1aSopenharmony_ci int port; 127cabdff1aSopenharmony_ci const char *p; 128cabdff1aSopenharmony_ci char proto[32]; 129cabdff1aSopenharmony_ci 130cabdff1aSopenharmony_ci av_url_split(proto, sizeof(proto), NULL, 0, dest_addr, size, &port, NULL, 0, url); 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_ci *ttl = 0; 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_ci if (strcmp(proto, "rtp") && strcmp(proto, "srtp")) { 135cabdff1aSopenharmony_ci /* The url isn't for the actual rtp sessions, 136cabdff1aSopenharmony_ci * don't parse out anything else than the destination. 137cabdff1aSopenharmony_ci */ 138cabdff1aSopenharmony_ci return 0; 139cabdff1aSopenharmony_ci } 140cabdff1aSopenharmony_ci 141cabdff1aSopenharmony_ci p = strchr(url, '?'); 142cabdff1aSopenharmony_ci if (p) { 143cabdff1aSopenharmony_ci char buff[64]; 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ci if (av_find_info_tag(buff, sizeof(buff), "ttl", p)) { 146cabdff1aSopenharmony_ci *ttl = strtol(buff, NULL, 10); 147cabdff1aSopenharmony_ci } else { 148cabdff1aSopenharmony_ci *ttl = 5; 149cabdff1aSopenharmony_ci } 150cabdff1aSopenharmony_ci } 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci return port; 153cabdff1aSopenharmony_ci} 154cabdff1aSopenharmony_ci 155cabdff1aSopenharmony_ci#define MAX_PSET_SIZE 1024 156cabdff1aSopenharmony_cistatic int extradata2psets(AVFormatContext *s, const AVCodecParameters *par, 157cabdff1aSopenharmony_ci char **out) 158cabdff1aSopenharmony_ci{ 159cabdff1aSopenharmony_ci char *psets, *p; 160cabdff1aSopenharmony_ci const uint8_t *r; 161cabdff1aSopenharmony_ci static const char pset_string[] = "; sprop-parameter-sets="; 162cabdff1aSopenharmony_ci static const char profile_string[] = "; profile-level-id="; 163cabdff1aSopenharmony_ci uint8_t *extradata = par->extradata; 164cabdff1aSopenharmony_ci int extradata_size = par->extradata_size; 165cabdff1aSopenharmony_ci uint8_t *tmpbuf = NULL; 166cabdff1aSopenharmony_ci const uint8_t *sps = NULL, *sps_end; 167cabdff1aSopenharmony_ci 168cabdff1aSopenharmony_ci *out = NULL; 169cabdff1aSopenharmony_ci 170cabdff1aSopenharmony_ci if (par->extradata_size > MAX_EXTRADATA_SIZE) { 171cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Too much extradata!\n"); 172cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 173cabdff1aSopenharmony_ci } 174cabdff1aSopenharmony_ci if (par->extradata[0] == 1) { 175cabdff1aSopenharmony_ci int ret = ff_avc_write_annexb_extradata(par->extradata, &extradata, 176cabdff1aSopenharmony_ci &extradata_size); 177cabdff1aSopenharmony_ci if (ret < 0) 178cabdff1aSopenharmony_ci return ret; 179cabdff1aSopenharmony_ci 180cabdff1aSopenharmony_ci tmpbuf = extradata; 181cabdff1aSopenharmony_ci } 182cabdff1aSopenharmony_ci 183cabdff1aSopenharmony_ci psets = av_mallocz(MAX_PSET_SIZE); 184cabdff1aSopenharmony_ci if (!psets) { 185cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the parameter sets.\n"); 186cabdff1aSopenharmony_ci av_free(tmpbuf); 187cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 188cabdff1aSopenharmony_ci } 189cabdff1aSopenharmony_ci memcpy(psets, pset_string, strlen(pset_string)); 190cabdff1aSopenharmony_ci p = psets + strlen(pset_string); 191cabdff1aSopenharmony_ci r = ff_avc_find_startcode(extradata, extradata + extradata_size); 192cabdff1aSopenharmony_ci while (r < extradata + extradata_size) { 193cabdff1aSopenharmony_ci const uint8_t *r1; 194cabdff1aSopenharmony_ci uint8_t nal_type; 195cabdff1aSopenharmony_ci 196cabdff1aSopenharmony_ci while (!*(r++)); 197cabdff1aSopenharmony_ci nal_type = *r & 0x1f; 198cabdff1aSopenharmony_ci r1 = ff_avc_find_startcode(r, extradata + extradata_size); 199cabdff1aSopenharmony_ci if (nal_type != 7 && nal_type != 8) { /* Only output SPS and PPS */ 200cabdff1aSopenharmony_ci r = r1; 201cabdff1aSopenharmony_ci continue; 202cabdff1aSopenharmony_ci } 203cabdff1aSopenharmony_ci if (p != (psets + strlen(pset_string))) { 204cabdff1aSopenharmony_ci *p = ','; 205cabdff1aSopenharmony_ci p++; 206cabdff1aSopenharmony_ci } 207cabdff1aSopenharmony_ci if (!sps) { 208cabdff1aSopenharmony_ci sps = r; 209cabdff1aSopenharmony_ci sps_end = r1; 210cabdff1aSopenharmony_ci } 211cabdff1aSopenharmony_ci if (!av_base64_encode(p, MAX_PSET_SIZE - (p - psets), r, r1 - r)) { 212cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Cannot Base64-encode %"PTRDIFF_SPECIFIER" %"PTRDIFF_SPECIFIER"!\n", 213cabdff1aSopenharmony_ci MAX_PSET_SIZE - (p - psets), r1 - r); 214cabdff1aSopenharmony_ci av_free(psets); 215cabdff1aSopenharmony_ci av_free(tmpbuf); 216cabdff1aSopenharmony_ci 217cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 218cabdff1aSopenharmony_ci } 219cabdff1aSopenharmony_ci p += strlen(p); 220cabdff1aSopenharmony_ci r = r1; 221cabdff1aSopenharmony_ci } 222cabdff1aSopenharmony_ci if (sps && sps_end - sps >= 4 && p - psets <= MAX_PSET_SIZE - strlen(profile_string) - 7) { 223cabdff1aSopenharmony_ci memcpy(p, profile_string, strlen(profile_string)); 224cabdff1aSopenharmony_ci p += strlen(p); 225cabdff1aSopenharmony_ci ff_data_to_hex(p, sps + 1, 3, 0); 226cabdff1aSopenharmony_ci } 227cabdff1aSopenharmony_ci av_free(tmpbuf); 228cabdff1aSopenharmony_ci 229cabdff1aSopenharmony_ci *out = psets; 230cabdff1aSopenharmony_ci return 0; 231cabdff1aSopenharmony_ci} 232cabdff1aSopenharmony_ci 233cabdff1aSopenharmony_cistatic int extradata2psets_hevc(const AVCodecParameters *par, char **out) 234cabdff1aSopenharmony_ci{ 235cabdff1aSopenharmony_ci char *psets; 236cabdff1aSopenharmony_ci uint8_t *extradata = par->extradata; 237cabdff1aSopenharmony_ci int extradata_size = par->extradata_size; 238cabdff1aSopenharmony_ci uint8_t *tmpbuf = NULL; 239cabdff1aSopenharmony_ci int ps_pos[3] = { 0 }; 240cabdff1aSopenharmony_ci static const char * const ps_names[3] = { "vps", "sps", "pps" }; 241cabdff1aSopenharmony_ci int num_arrays, num_nalus; 242cabdff1aSopenharmony_ci int pos, i, j, ret = 0; 243cabdff1aSopenharmony_ci 244cabdff1aSopenharmony_ci *out = NULL; 245cabdff1aSopenharmony_ci 246cabdff1aSopenharmony_ci // Convert to hvcc format. Since we need to group multiple NALUs of 247cabdff1aSopenharmony_ci // the same type, and we might need to convert from one format to the 248cabdff1aSopenharmony_ci // other anyway, we get away with a little less work by using the hvcc 249cabdff1aSopenharmony_ci // format. 250cabdff1aSopenharmony_ci if (par->extradata[0] != 1) { 251cabdff1aSopenharmony_ci AVIOContext *pb; 252cabdff1aSopenharmony_ci 253cabdff1aSopenharmony_ci ret = avio_open_dyn_buf(&pb); 254cabdff1aSopenharmony_ci if (ret < 0) 255cabdff1aSopenharmony_ci return ret; 256cabdff1aSopenharmony_ci 257cabdff1aSopenharmony_ci ret = ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0); 258cabdff1aSopenharmony_ci if (ret < 0) { 259cabdff1aSopenharmony_ci avio_close_dyn_buf(pb, &tmpbuf); 260cabdff1aSopenharmony_ci goto err; 261cabdff1aSopenharmony_ci } 262cabdff1aSopenharmony_ci extradata_size = avio_close_dyn_buf(pb, &extradata); 263cabdff1aSopenharmony_ci tmpbuf = extradata; 264cabdff1aSopenharmony_ci } 265cabdff1aSopenharmony_ci 266cabdff1aSopenharmony_ci if (extradata_size < 23) 267cabdff1aSopenharmony_ci goto err; 268cabdff1aSopenharmony_ci 269cabdff1aSopenharmony_ci num_arrays = extradata[22]; 270cabdff1aSopenharmony_ci pos = 23; 271cabdff1aSopenharmony_ci for (i = 0; i < num_arrays; i++) { 272cabdff1aSopenharmony_ci int num_nalus, nalu_type; 273cabdff1aSopenharmony_ci if (pos + 3 > extradata_size) 274cabdff1aSopenharmony_ci goto err; 275cabdff1aSopenharmony_ci nalu_type = extradata[pos] & 0x3f; 276cabdff1aSopenharmony_ci // Not including libavcodec/hevc.h to avoid confusion between 277cabdff1aSopenharmony_ci // NAL_* with the same name for both H.264 and HEVC. 278cabdff1aSopenharmony_ci if (nalu_type == 32) // VPS 279cabdff1aSopenharmony_ci ps_pos[0] = pos; 280cabdff1aSopenharmony_ci else if (nalu_type == 33) // SPS 281cabdff1aSopenharmony_ci ps_pos[1] = pos; 282cabdff1aSopenharmony_ci else if (nalu_type == 34) // PPS 283cabdff1aSopenharmony_ci ps_pos[2] = pos; 284cabdff1aSopenharmony_ci num_nalus = AV_RB16(&extradata[pos + 1]); 285cabdff1aSopenharmony_ci pos += 3; 286cabdff1aSopenharmony_ci for (j = 0; j < num_nalus; j++) { 287cabdff1aSopenharmony_ci int len; 288cabdff1aSopenharmony_ci if (pos + 2 > extradata_size) 289cabdff1aSopenharmony_ci goto err; 290cabdff1aSopenharmony_ci len = AV_RB16(&extradata[pos]); 291cabdff1aSopenharmony_ci pos += 2; 292cabdff1aSopenharmony_ci if (pos + len > extradata_size) 293cabdff1aSopenharmony_ci goto err; 294cabdff1aSopenharmony_ci pos += len; 295cabdff1aSopenharmony_ci } 296cabdff1aSopenharmony_ci } 297cabdff1aSopenharmony_ci if (!ps_pos[0] || !ps_pos[1] || !ps_pos[2]) 298cabdff1aSopenharmony_ci goto err; 299cabdff1aSopenharmony_ci 300cabdff1aSopenharmony_ci psets = av_mallocz(MAX_PSET_SIZE); 301cabdff1aSopenharmony_ci if (!psets) { 302cabdff1aSopenharmony_ci ret = AVERROR(ENOMEM); 303cabdff1aSopenharmony_ci goto err; 304cabdff1aSopenharmony_ci } 305cabdff1aSopenharmony_ci 306cabdff1aSopenharmony_ci psets[0] = '\0'; 307cabdff1aSopenharmony_ci 308cabdff1aSopenharmony_ci for (i = 0; i < 3; i++) { 309cabdff1aSopenharmony_ci pos = ps_pos[i]; 310cabdff1aSopenharmony_ci 311cabdff1aSopenharmony_ci if (i > 0) 312cabdff1aSopenharmony_ci av_strlcat(psets, "; ", MAX_PSET_SIZE); 313cabdff1aSopenharmony_ci av_strlcatf(psets, MAX_PSET_SIZE, "sprop-%s=", ps_names[i]); 314cabdff1aSopenharmony_ci 315cabdff1aSopenharmony_ci // Skipping boundary checks in the input here; we've already traversed 316cabdff1aSopenharmony_ci // the whole hvcc structure above without issues 317cabdff1aSopenharmony_ci num_nalus = AV_RB16(&extradata[pos + 1]); 318cabdff1aSopenharmony_ci pos += 3; 319cabdff1aSopenharmony_ci for (j = 0; j < num_nalus; j++) { 320cabdff1aSopenharmony_ci int len = AV_RB16(&extradata[pos]); 321cabdff1aSopenharmony_ci int strpos; 322cabdff1aSopenharmony_ci pos += 2; 323cabdff1aSopenharmony_ci if (j > 0) 324cabdff1aSopenharmony_ci av_strlcat(psets, ",", MAX_PSET_SIZE); 325cabdff1aSopenharmony_ci strpos = strlen(psets); 326cabdff1aSopenharmony_ci if (!av_base64_encode(psets + strpos, MAX_PSET_SIZE - strpos, 327cabdff1aSopenharmony_ci &extradata[pos], len)) { 328cabdff1aSopenharmony_ci av_free(psets); 329cabdff1aSopenharmony_ci goto err; 330cabdff1aSopenharmony_ci } 331cabdff1aSopenharmony_ci pos += len; 332cabdff1aSopenharmony_ci } 333cabdff1aSopenharmony_ci } 334cabdff1aSopenharmony_ci av_free(tmpbuf); 335cabdff1aSopenharmony_ci 336cabdff1aSopenharmony_ci *out = psets; 337cabdff1aSopenharmony_ci return 0; 338cabdff1aSopenharmony_cierr: 339cabdff1aSopenharmony_ci if (ret >= 0) 340cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 341cabdff1aSopenharmony_ci av_free(tmpbuf); 342cabdff1aSopenharmony_ci return ret; 343cabdff1aSopenharmony_ci} 344cabdff1aSopenharmony_ci 345cabdff1aSopenharmony_cistatic int extradata2config(AVFormatContext *s, const AVCodecParameters *par, 346cabdff1aSopenharmony_ci char **out) 347cabdff1aSopenharmony_ci{ 348cabdff1aSopenharmony_ci char *config; 349cabdff1aSopenharmony_ci 350cabdff1aSopenharmony_ci *out = NULL; 351cabdff1aSopenharmony_ci 352cabdff1aSopenharmony_ci if (par->extradata_size > MAX_EXTRADATA_SIZE) { 353cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Too much extradata!\n"); 354cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 355cabdff1aSopenharmony_ci } 356cabdff1aSopenharmony_ci config = av_malloc(10 + par->extradata_size * 2); 357cabdff1aSopenharmony_ci if (!config) { 358cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n"); 359cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 360cabdff1aSopenharmony_ci } 361cabdff1aSopenharmony_ci memcpy(config, "; config=", 9); 362cabdff1aSopenharmony_ci ff_data_to_hex(config + 9, par->extradata, par->extradata_size, 0); 363cabdff1aSopenharmony_ci 364cabdff1aSopenharmony_ci *out = config; 365cabdff1aSopenharmony_ci return 0; 366cabdff1aSopenharmony_ci} 367cabdff1aSopenharmony_ci 368cabdff1aSopenharmony_cistatic int xiph_extradata2config(AVFormatContext *s, const AVCodecParameters *par, 369cabdff1aSopenharmony_ci char **out) 370cabdff1aSopenharmony_ci{ 371cabdff1aSopenharmony_ci uint8_t *config; 372cabdff1aSopenharmony_ci char *encoded_config; 373cabdff1aSopenharmony_ci const uint8_t *header_start[3]; 374cabdff1aSopenharmony_ci int headers_len, header_len[3], config_len; 375cabdff1aSopenharmony_ci int first_header_size, ret; 376cabdff1aSopenharmony_ci 377cabdff1aSopenharmony_ci *out = NULL; 378cabdff1aSopenharmony_ci 379cabdff1aSopenharmony_ci switch (par->codec_id) { 380cabdff1aSopenharmony_ci case AV_CODEC_ID_THEORA: 381cabdff1aSopenharmony_ci first_header_size = 42; 382cabdff1aSopenharmony_ci break; 383cabdff1aSopenharmony_ci case AV_CODEC_ID_VORBIS: 384cabdff1aSopenharmony_ci first_header_size = 30; 385cabdff1aSopenharmony_ci break; 386cabdff1aSopenharmony_ci default: 387cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Unsupported Xiph codec ID\n"); 388cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 389cabdff1aSopenharmony_ci } 390cabdff1aSopenharmony_ci 391cabdff1aSopenharmony_ci ret = avpriv_split_xiph_headers(par->extradata, par->extradata_size, 392cabdff1aSopenharmony_ci first_header_size, header_start, 393cabdff1aSopenharmony_ci header_len); 394cabdff1aSopenharmony_ci if (ret < 0) { 395cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n"); 396cabdff1aSopenharmony_ci return ret; 397cabdff1aSopenharmony_ci } 398cabdff1aSopenharmony_ci 399cabdff1aSopenharmony_ci headers_len = header_len[0] + header_len[2]; 400cabdff1aSopenharmony_ci config_len = 4 + // count 401cabdff1aSopenharmony_ci 3 + // ident 402cabdff1aSopenharmony_ci 2 + // packet size 403cabdff1aSopenharmony_ci 1 + // header count 404cabdff1aSopenharmony_ci 2 + // header size 405cabdff1aSopenharmony_ci headers_len; // and the rest 406cabdff1aSopenharmony_ci 407cabdff1aSopenharmony_ci config = av_malloc(config_len); 408cabdff1aSopenharmony_ci if (!config) 409cabdff1aSopenharmony_ci goto xiph_fail; 410cabdff1aSopenharmony_ci 411cabdff1aSopenharmony_ci encoded_config = av_malloc(AV_BASE64_SIZE(config_len)); 412cabdff1aSopenharmony_ci if (!encoded_config) { 413cabdff1aSopenharmony_ci av_free(config); 414cabdff1aSopenharmony_ci goto xiph_fail; 415cabdff1aSopenharmony_ci } 416cabdff1aSopenharmony_ci 417cabdff1aSopenharmony_ci config[0] = config[1] = config[2] = 0; 418cabdff1aSopenharmony_ci config[3] = 1; 419cabdff1aSopenharmony_ci config[4] = (RTP_XIPH_IDENT >> 16) & 0xff; 420cabdff1aSopenharmony_ci config[5] = (RTP_XIPH_IDENT >> 8) & 0xff; 421cabdff1aSopenharmony_ci config[6] = (RTP_XIPH_IDENT ) & 0xff; 422cabdff1aSopenharmony_ci config[7] = (headers_len >> 8) & 0xff; 423cabdff1aSopenharmony_ci config[8] = headers_len & 0xff; 424cabdff1aSopenharmony_ci config[9] = 2; 425cabdff1aSopenharmony_ci config[10] = header_len[0]; 426cabdff1aSopenharmony_ci config[11] = 0; // size of comment header; nonexistent 427cabdff1aSopenharmony_ci memcpy(config + 12, header_start[0], header_len[0]); 428cabdff1aSopenharmony_ci memcpy(config + 12 + header_len[0], header_start[2], header_len[2]); 429cabdff1aSopenharmony_ci 430cabdff1aSopenharmony_ci av_base64_encode(encoded_config, AV_BASE64_SIZE(config_len), 431cabdff1aSopenharmony_ci config, config_len); 432cabdff1aSopenharmony_ci av_free(config); 433cabdff1aSopenharmony_ci 434cabdff1aSopenharmony_ci *out = encoded_config; 435cabdff1aSopenharmony_ci return 0; 436cabdff1aSopenharmony_ci 437cabdff1aSopenharmony_cixiph_fail: 438cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, 439cabdff1aSopenharmony_ci "Not enough memory for configuration string\n"); 440cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 441cabdff1aSopenharmony_ci} 442cabdff1aSopenharmony_ci 443cabdff1aSopenharmony_cistatic int latm_context2profilelevel(const AVCodecParameters *par) 444cabdff1aSopenharmony_ci{ 445cabdff1aSopenharmony_ci /* MP4A-LATM 446cabdff1aSopenharmony_ci * The RTP payload format specification is described in RFC 3016 447cabdff1aSopenharmony_ci * The encoding specifications are provided in ISO/IEC 14496-3 */ 448cabdff1aSopenharmony_ci 449cabdff1aSopenharmony_ci int profile_level = 0x2B; 450cabdff1aSopenharmony_ci 451cabdff1aSopenharmony_ci /* TODO: AAC Profile only supports AAC LC Object Type. 452cabdff1aSopenharmony_ci * Different Object Types should implement different Profile Levels */ 453cabdff1aSopenharmony_ci 454cabdff1aSopenharmony_ci if (par->sample_rate <= 24000) { 455cabdff1aSopenharmony_ci if (par->ch_layout.nb_channels <= 2) 456cabdff1aSopenharmony_ci profile_level = 0x28; // AAC Profile, Level 1 457cabdff1aSopenharmony_ci } else if (par->sample_rate <= 48000) { 458cabdff1aSopenharmony_ci if (par->ch_layout.nb_channels <= 2) { 459cabdff1aSopenharmony_ci profile_level = 0x29; // AAC Profile, Level 2 460cabdff1aSopenharmony_ci } else if (par->ch_layout.nb_channels <= 5) { 461cabdff1aSopenharmony_ci profile_level = 0x2A; // AAC Profile, Level 4 462cabdff1aSopenharmony_ci } 463cabdff1aSopenharmony_ci } else if (par->sample_rate <= 96000) { 464cabdff1aSopenharmony_ci if (par->ch_layout.nb_channels <= 5) { 465cabdff1aSopenharmony_ci profile_level = 0x2B; // AAC Profile, Level 5 466cabdff1aSopenharmony_ci } 467cabdff1aSopenharmony_ci } 468cabdff1aSopenharmony_ci 469cabdff1aSopenharmony_ci return profile_level; 470cabdff1aSopenharmony_ci} 471cabdff1aSopenharmony_ci 472cabdff1aSopenharmony_cistatic int latm_context2config(AVFormatContext *s, const AVCodecParameters *par, 473cabdff1aSopenharmony_ci char **out) 474cabdff1aSopenharmony_ci{ 475cabdff1aSopenharmony_ci /* MP4A-LATM 476cabdff1aSopenharmony_ci * The RTP payload format specification is described in RFC 3016 477cabdff1aSopenharmony_ci * The encoding specifications are provided in ISO/IEC 14496-3 */ 478cabdff1aSopenharmony_ci 479cabdff1aSopenharmony_ci uint8_t config_byte[6]; 480cabdff1aSopenharmony_ci int rate_index; 481cabdff1aSopenharmony_ci char *config; 482cabdff1aSopenharmony_ci 483cabdff1aSopenharmony_ci *out = NULL; 484cabdff1aSopenharmony_ci 485cabdff1aSopenharmony_ci for (rate_index = 0; rate_index < 16; rate_index++) 486cabdff1aSopenharmony_ci if (ff_mpeg4audio_sample_rates[rate_index] == par->sample_rate) 487cabdff1aSopenharmony_ci break; 488cabdff1aSopenharmony_ci if (rate_index == 16) { 489cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n"); 490cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 491cabdff1aSopenharmony_ci } 492cabdff1aSopenharmony_ci 493cabdff1aSopenharmony_ci config_byte[0] = 0x40; 494cabdff1aSopenharmony_ci config_byte[1] = 0; 495cabdff1aSopenharmony_ci config_byte[2] = 0x20 | rate_index; 496cabdff1aSopenharmony_ci config_byte[3] = par->ch_layout.nb_channels << 4; 497cabdff1aSopenharmony_ci config_byte[4] = 0x3f; 498cabdff1aSopenharmony_ci config_byte[5] = 0xc0; 499cabdff1aSopenharmony_ci 500cabdff1aSopenharmony_ci config = av_malloc(6*2+1); 501cabdff1aSopenharmony_ci if (!config) { 502cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n"); 503cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 504cabdff1aSopenharmony_ci } 505cabdff1aSopenharmony_ci ff_data_to_hex(config, config_byte, 6, 1); 506cabdff1aSopenharmony_ci 507cabdff1aSopenharmony_ci *out = config; 508cabdff1aSopenharmony_ci return 0; 509cabdff1aSopenharmony_ci} 510cabdff1aSopenharmony_ci 511cabdff1aSopenharmony_cistatic int sdp_write_media_attributes(char *buff, int size, const AVStream *st, 512cabdff1aSopenharmony_ci int payload_type, AVFormatContext *fmt) 513cabdff1aSopenharmony_ci{ 514cabdff1aSopenharmony_ci char *config = NULL; 515cabdff1aSopenharmony_ci const AVCodecParameters *p = st->codecpar; 516cabdff1aSopenharmony_ci int ret = 0; 517cabdff1aSopenharmony_ci 518cabdff1aSopenharmony_ci switch (p->codec_id) { 519cabdff1aSopenharmony_ci case AV_CODEC_ID_DIRAC: 520cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d VC2/90000\r\n", payload_type); 521cabdff1aSopenharmony_ci break; 522cabdff1aSopenharmony_ci case AV_CODEC_ID_H264: { 523cabdff1aSopenharmony_ci int mode = 1; 524cabdff1aSopenharmony_ci if (fmt && fmt->oformat && fmt->oformat->priv_class && 525cabdff1aSopenharmony_ci av_opt_flag_is_set(fmt->priv_data, "rtpflags", "h264_mode0")) 526cabdff1aSopenharmony_ci mode = 0; 527cabdff1aSopenharmony_ci if (p->extradata_size) { 528cabdff1aSopenharmony_ci ret = extradata2psets(fmt, p, &config); 529cabdff1aSopenharmony_ci if (ret < 0) 530cabdff1aSopenharmony_ci return ret; 531cabdff1aSopenharmony_ci } 532cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d H264/90000\r\n" 533cabdff1aSopenharmony_ci "a=fmtp:%d packetization-mode=%d%s\r\n", 534cabdff1aSopenharmony_ci payload_type, 535cabdff1aSopenharmony_ci payload_type, mode, config ? config : ""); 536cabdff1aSopenharmony_ci break; 537cabdff1aSopenharmony_ci } 538cabdff1aSopenharmony_ci case AV_CODEC_ID_H261: 539cabdff1aSopenharmony_ci { 540cabdff1aSopenharmony_ci const char *pic_fmt = NULL; 541cabdff1aSopenharmony_ci /* only QCIF and CIF are specified as supported in RFC 4587 */ 542cabdff1aSopenharmony_ci if (p->width == 176 && p->height == 144) 543cabdff1aSopenharmony_ci pic_fmt = "QCIF=1"; 544cabdff1aSopenharmony_ci else if (p->width == 352 && p->height == 288) 545cabdff1aSopenharmony_ci pic_fmt = "CIF=1"; 546cabdff1aSopenharmony_ci if (payload_type >= RTP_PT_PRIVATE) 547cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d H261/90000\r\n", payload_type); 548cabdff1aSopenharmony_ci if (pic_fmt) 549cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=fmtp:%d %s\r\n", payload_type, pic_fmt); 550cabdff1aSopenharmony_ci break; 551cabdff1aSopenharmony_ci } 552cabdff1aSopenharmony_ci case AV_CODEC_ID_H263: 553cabdff1aSopenharmony_ci case AV_CODEC_ID_H263P: 554cabdff1aSopenharmony_ci /* a=framesize is required by 3GPP TS 26.234 (PSS). It 555cabdff1aSopenharmony_ci * actually specifies the maximum video size, but we only know 556cabdff1aSopenharmony_ci * the current size. This is required for playback on Android 557cabdff1aSopenharmony_ci * stagefright and on Samsung bada. */ 558cabdff1aSopenharmony_ci if (!fmt || !fmt->oformat->priv_class || 559cabdff1aSopenharmony_ci !av_opt_flag_is_set(fmt->priv_data, "rtpflags", "rfc2190") || 560cabdff1aSopenharmony_ci p->codec_id == AV_CODEC_ID_H263P) 561cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d H263-2000/90000\r\n" 562cabdff1aSopenharmony_ci "a=framesize:%d %d-%d\r\n", 563cabdff1aSopenharmony_ci payload_type, 564cabdff1aSopenharmony_ci payload_type, p->width, p->height); 565cabdff1aSopenharmony_ci break; 566cabdff1aSopenharmony_ci case AV_CODEC_ID_HEVC: 567cabdff1aSopenharmony_ci if (p->extradata_size) { 568cabdff1aSopenharmony_ci ret = extradata2psets_hevc(p, &config); 569cabdff1aSopenharmony_ci if (ret < 0) 570cabdff1aSopenharmony_ci return ret; 571cabdff1aSopenharmony_ci } 572cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d H265/90000\r\n", payload_type); 573cabdff1aSopenharmony_ci if (config) 574cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=fmtp:%d %s\r\n", 575cabdff1aSopenharmony_ci payload_type, config); 576cabdff1aSopenharmony_ci break; 577cabdff1aSopenharmony_ci case AV_CODEC_ID_MPEG4: 578cabdff1aSopenharmony_ci if (p->extradata_size) { 579cabdff1aSopenharmony_ci ret = extradata2config(fmt, p, &config); 580cabdff1aSopenharmony_ci if (ret < 0) 581cabdff1aSopenharmony_ci return ret; 582cabdff1aSopenharmony_ci } 583cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d MP4V-ES/90000\r\n" 584cabdff1aSopenharmony_ci "a=fmtp:%d profile-level-id=1%s\r\n", 585cabdff1aSopenharmony_ci payload_type, 586cabdff1aSopenharmony_ci payload_type, config ? config : ""); 587cabdff1aSopenharmony_ci break; 588cabdff1aSopenharmony_ci case AV_CODEC_ID_AAC: 589cabdff1aSopenharmony_ci if (fmt && fmt->oformat && fmt->oformat->priv_class && 590cabdff1aSopenharmony_ci av_opt_flag_is_set(fmt->priv_data, "rtpflags", "latm")) { 591cabdff1aSopenharmony_ci ret = latm_context2config(fmt, p, &config); 592cabdff1aSopenharmony_ci if (ret < 0) 593cabdff1aSopenharmony_ci return ret; 594cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d MP4A-LATM/%d/%d\r\n" 595cabdff1aSopenharmony_ci "a=fmtp:%d profile-level-id=%d;cpresent=0;config=%s\r\n", 596cabdff1aSopenharmony_ci payload_type, p->sample_rate, p->ch_layout.nb_channels, 597cabdff1aSopenharmony_ci payload_type, latm_context2profilelevel(p), config); 598cabdff1aSopenharmony_ci } else { 599cabdff1aSopenharmony_ci if (p->extradata_size) { 600cabdff1aSopenharmony_ci ret = extradata2config(fmt, p, &config); 601cabdff1aSopenharmony_ci if (ret < 0) 602cabdff1aSopenharmony_ci return ret; 603cabdff1aSopenharmony_ci } else { 604cabdff1aSopenharmony_ci /* FIXME: maybe we can forge config information based on the 605cabdff1aSopenharmony_ci * codec parameters... 606cabdff1aSopenharmony_ci */ 607cabdff1aSopenharmony_ci av_log(fmt, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n"); 608cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 609cabdff1aSopenharmony_ci } 610cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n" 611cabdff1aSopenharmony_ci "a=fmtp:%d profile-level-id=1;" 612cabdff1aSopenharmony_ci "mode=AAC-hbr;sizelength=13;indexlength=3;" 613cabdff1aSopenharmony_ci "indexdeltalength=3%s\r\n", 614cabdff1aSopenharmony_ci payload_type, p->sample_rate, p->ch_layout.nb_channels, 615cabdff1aSopenharmony_ci payload_type, config); 616cabdff1aSopenharmony_ci } 617cabdff1aSopenharmony_ci break; 618cabdff1aSopenharmony_ci case AV_CODEC_ID_PCM_S16BE: 619cabdff1aSopenharmony_ci if (payload_type >= RTP_PT_PRIVATE) 620cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d L16/%d/%d\r\n", 621cabdff1aSopenharmony_ci payload_type, 622cabdff1aSopenharmony_ci p->sample_rate, p->ch_layout.nb_channels); 623cabdff1aSopenharmony_ci break; 624cabdff1aSopenharmony_ci case AV_CODEC_ID_PCM_S24BE: 625cabdff1aSopenharmony_ci if (payload_type >= RTP_PT_PRIVATE) 626cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d L24/%d/%d\r\n", 627cabdff1aSopenharmony_ci payload_type, 628cabdff1aSopenharmony_ci p->sample_rate, p->ch_layout.nb_channels); 629cabdff1aSopenharmony_ci break; 630cabdff1aSopenharmony_ci case AV_CODEC_ID_PCM_MULAW: 631cabdff1aSopenharmony_ci if (payload_type >= RTP_PT_PRIVATE) 632cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d PCMU/%d/%d\r\n", 633cabdff1aSopenharmony_ci payload_type, 634cabdff1aSopenharmony_ci p->sample_rate, p->ch_layout.nb_channels); 635cabdff1aSopenharmony_ci break; 636cabdff1aSopenharmony_ci case AV_CODEC_ID_PCM_ALAW: 637cabdff1aSopenharmony_ci if (payload_type >= RTP_PT_PRIVATE) 638cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d PCMA/%d/%d\r\n", 639cabdff1aSopenharmony_ci payload_type, 640cabdff1aSopenharmony_ci p->sample_rate, p->ch_layout.nb_channels); 641cabdff1aSopenharmony_ci break; 642cabdff1aSopenharmony_ci case AV_CODEC_ID_AMR_NB: 643cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d AMR/%d/%d\r\n" 644cabdff1aSopenharmony_ci "a=fmtp:%d octet-align=1\r\n", 645cabdff1aSopenharmony_ci payload_type, p->sample_rate, p->ch_layout.nb_channels, 646cabdff1aSopenharmony_ci payload_type); 647cabdff1aSopenharmony_ci break; 648cabdff1aSopenharmony_ci case AV_CODEC_ID_AMR_WB: 649cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d AMR-WB/%d/%d\r\n" 650cabdff1aSopenharmony_ci "a=fmtp:%d octet-align=1\r\n", 651cabdff1aSopenharmony_ci payload_type, p->sample_rate, p->ch_layout.nb_channels, 652cabdff1aSopenharmony_ci payload_type); 653cabdff1aSopenharmony_ci break; 654cabdff1aSopenharmony_ci case AV_CODEC_ID_VORBIS: 655cabdff1aSopenharmony_ci if (p->extradata_size) 656cabdff1aSopenharmony_ci ret = xiph_extradata2config(fmt, p, &config); 657cabdff1aSopenharmony_ci else { 658cabdff1aSopenharmony_ci av_log(fmt, AV_LOG_ERROR, "Vorbis configuration info missing\n"); 659cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 660cabdff1aSopenharmony_ci } 661cabdff1aSopenharmony_ci if (ret < 0) 662cabdff1aSopenharmony_ci return ret; 663cabdff1aSopenharmony_ci 664cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d vorbis/%d/%d\r\n" 665cabdff1aSopenharmony_ci "a=fmtp:%d configuration=%s\r\n", 666cabdff1aSopenharmony_ci payload_type, p->sample_rate, p->ch_layout.nb_channels, 667cabdff1aSopenharmony_ci payload_type, config); 668cabdff1aSopenharmony_ci break; 669cabdff1aSopenharmony_ci case AV_CODEC_ID_THEORA: { 670cabdff1aSopenharmony_ci const char *pix_fmt; 671cabdff1aSopenharmony_ci switch (p->format) { 672cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV420P: 673cabdff1aSopenharmony_ci pix_fmt = "YCbCr-4:2:0"; 674cabdff1aSopenharmony_ci break; 675cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV422P: 676cabdff1aSopenharmony_ci pix_fmt = "YCbCr-4:2:2"; 677cabdff1aSopenharmony_ci break; 678cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV444P: 679cabdff1aSopenharmony_ci pix_fmt = "YCbCr-4:4:4"; 680cabdff1aSopenharmony_ci break; 681cabdff1aSopenharmony_ci default: 682cabdff1aSopenharmony_ci av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n"); 683cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 684cabdff1aSopenharmony_ci } 685cabdff1aSopenharmony_ci 686cabdff1aSopenharmony_ci if (p->extradata_size) 687cabdff1aSopenharmony_ci ret = xiph_extradata2config(fmt, p, &config); 688cabdff1aSopenharmony_ci else { 689cabdff1aSopenharmony_ci av_log(fmt, AV_LOG_ERROR, "Theora configuration info missing\n"); 690cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 691cabdff1aSopenharmony_ci } 692cabdff1aSopenharmony_ci if (ret < 0) 693cabdff1aSopenharmony_ci return ret; 694cabdff1aSopenharmony_ci 695cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d theora/90000\r\n" 696cabdff1aSopenharmony_ci "a=fmtp:%d delivery-method=inline; " 697cabdff1aSopenharmony_ci "width=%d; height=%d; sampling=%s; " 698cabdff1aSopenharmony_ci "configuration=%s\r\n", 699cabdff1aSopenharmony_ci payload_type, payload_type, 700cabdff1aSopenharmony_ci p->width, p->height, pix_fmt, config); 701cabdff1aSopenharmony_ci break; 702cabdff1aSopenharmony_ci } 703cabdff1aSopenharmony_ci case AV_CODEC_ID_BITPACKED: 704cabdff1aSopenharmony_ci case AV_CODEC_ID_RAWVIDEO: { 705cabdff1aSopenharmony_ci const char *pix_fmt; 706cabdff1aSopenharmony_ci int bit_depth = 8; 707cabdff1aSopenharmony_ci 708cabdff1aSopenharmony_ci switch (p->format) { 709cabdff1aSopenharmony_ci case AV_PIX_FMT_UYVY422: 710cabdff1aSopenharmony_ci pix_fmt = "YCbCr-4:2:2"; 711cabdff1aSopenharmony_ci break; 712cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV422P10: 713cabdff1aSopenharmony_ci pix_fmt = "YCbCr-4:2:2"; 714cabdff1aSopenharmony_ci bit_depth = 10; 715cabdff1aSopenharmony_ci break; 716cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV420P: 717cabdff1aSopenharmony_ci pix_fmt = "YCbCr-4:2:0"; 718cabdff1aSopenharmony_ci break; 719cabdff1aSopenharmony_ci case AV_PIX_FMT_RGB24: 720cabdff1aSopenharmony_ci pix_fmt = "RGB"; 721cabdff1aSopenharmony_ci break; 722cabdff1aSopenharmony_ci case AV_PIX_FMT_BGR24: 723cabdff1aSopenharmony_ci pix_fmt = "BGR"; 724cabdff1aSopenharmony_ci break; 725cabdff1aSopenharmony_ci default: 726cabdff1aSopenharmony_ci av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n"); 727cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 728cabdff1aSopenharmony_ci } 729cabdff1aSopenharmony_ci 730cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d raw/90000\r\n" 731cabdff1aSopenharmony_ci "a=fmtp:%d sampling=%s; " 732cabdff1aSopenharmony_ci "width=%d; height=%d; " 733cabdff1aSopenharmony_ci "depth=%d", 734cabdff1aSopenharmony_ci payload_type, payload_type, 735cabdff1aSopenharmony_ci pix_fmt, p->width, p->height, bit_depth); 736cabdff1aSopenharmony_ci if (p->field_order != AV_FIELD_PROGRESSIVE) 737cabdff1aSopenharmony_ci av_strlcatf(buff, size, "; interlace"); 738cabdff1aSopenharmony_ci av_strlcatf(buff, size, "\r\n"); 739cabdff1aSopenharmony_ci break; 740cabdff1aSopenharmony_ci } 741cabdff1aSopenharmony_ci 742cabdff1aSopenharmony_ci case AV_CODEC_ID_VP8: 743cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d VP8/90000\r\n", 744cabdff1aSopenharmony_ci payload_type); 745cabdff1aSopenharmony_ci break; 746cabdff1aSopenharmony_ci case AV_CODEC_ID_VP9: 747cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d VP9/90000\r\n", 748cabdff1aSopenharmony_ci payload_type); 749cabdff1aSopenharmony_ci break; 750cabdff1aSopenharmony_ci case AV_CODEC_ID_MJPEG: 751cabdff1aSopenharmony_ci if (payload_type >= RTP_PT_PRIVATE) 752cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d JPEG/90000\r\n", 753cabdff1aSopenharmony_ci payload_type); 754cabdff1aSopenharmony_ci break; 755cabdff1aSopenharmony_ci case AV_CODEC_ID_ADPCM_G722: 756cabdff1aSopenharmony_ci if (payload_type >= RTP_PT_PRIVATE) 757cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d G722/%d/%d\r\n", 758cabdff1aSopenharmony_ci payload_type, 759cabdff1aSopenharmony_ci 8000, p->ch_layout.nb_channels); 760cabdff1aSopenharmony_ci break; 761cabdff1aSopenharmony_ci case AV_CODEC_ID_ADPCM_G726: { 762cabdff1aSopenharmony_ci if (payload_type >= RTP_PT_PRIVATE) 763cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d AAL2-G726-%d/%d\r\n", 764cabdff1aSopenharmony_ci payload_type, 765cabdff1aSopenharmony_ci p->bits_per_coded_sample*8, 766cabdff1aSopenharmony_ci p->sample_rate); 767cabdff1aSopenharmony_ci break; 768cabdff1aSopenharmony_ci } 769cabdff1aSopenharmony_ci case AV_CODEC_ID_ADPCM_G726LE: { 770cabdff1aSopenharmony_ci if (payload_type >= RTP_PT_PRIVATE) 771cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d G726-%d/%d\r\n", 772cabdff1aSopenharmony_ci payload_type, 773cabdff1aSopenharmony_ci p->bits_per_coded_sample*8, 774cabdff1aSopenharmony_ci p->sample_rate); 775cabdff1aSopenharmony_ci break; 776cabdff1aSopenharmony_ci } 777cabdff1aSopenharmony_ci case AV_CODEC_ID_ILBC: 778cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d iLBC/%d\r\n" 779cabdff1aSopenharmony_ci "a=fmtp:%d mode=%d\r\n", 780cabdff1aSopenharmony_ci payload_type, p->sample_rate, 781cabdff1aSopenharmony_ci payload_type, p->block_align == 38 ? 20 : 30); 782cabdff1aSopenharmony_ci break; 783cabdff1aSopenharmony_ci case AV_CODEC_ID_SPEEX: 784cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d speex/%d\r\n", 785cabdff1aSopenharmony_ci payload_type, p->sample_rate); 786cabdff1aSopenharmony_ci break; 787cabdff1aSopenharmony_ci case AV_CODEC_ID_OPUS: 788cabdff1aSopenharmony_ci /* The opus RTP draft says that all opus streams MUST be declared 789cabdff1aSopenharmony_ci as stereo, to avoid negotiation failures. The actual number of 790cabdff1aSopenharmony_ci channels can change on a packet-by-packet basis. The number of 791cabdff1aSopenharmony_ci channels a receiver prefers to receive or a sender plans to send 792cabdff1aSopenharmony_ci can be declared via fmtp parameters (both default to mono), but 793cabdff1aSopenharmony_ci receivers MUST be able to receive and process stereo packets. */ 794cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=rtpmap:%d opus/48000/2\r\n", 795cabdff1aSopenharmony_ci payload_type); 796cabdff1aSopenharmony_ci if (p->ch_layout.nb_channels == 2) { 797cabdff1aSopenharmony_ci av_strlcatf(buff, size, "a=fmtp:%d sprop-stereo=1\r\n", 798cabdff1aSopenharmony_ci payload_type); 799cabdff1aSopenharmony_ci } 800cabdff1aSopenharmony_ci break; 801cabdff1aSopenharmony_ci default: 802cabdff1aSopenharmony_ci /* Nothing special to do here... */ 803cabdff1aSopenharmony_ci break; 804cabdff1aSopenharmony_ci } 805cabdff1aSopenharmony_ci 806cabdff1aSopenharmony_ci av_free(config); 807cabdff1aSopenharmony_ci 808cabdff1aSopenharmony_ci return 0; 809cabdff1aSopenharmony_ci} 810cabdff1aSopenharmony_ci 811cabdff1aSopenharmony_ciint ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx, 812cabdff1aSopenharmony_ci const char *dest_addr, const char *dest_type, 813cabdff1aSopenharmony_ci int port, int ttl, AVFormatContext *fmt) 814cabdff1aSopenharmony_ci{ 815cabdff1aSopenharmony_ci const AVCodecParameters *p = st->codecpar; 816cabdff1aSopenharmony_ci const char *type; 817cabdff1aSopenharmony_ci int payload_type; 818cabdff1aSopenharmony_ci 819cabdff1aSopenharmony_ci payload_type = ff_rtp_get_payload_type(fmt, st->codecpar, idx); 820cabdff1aSopenharmony_ci 821cabdff1aSopenharmony_ci switch (p->codec_type) { 822cabdff1aSopenharmony_ci case AVMEDIA_TYPE_VIDEO : type = "video" ; break; 823cabdff1aSopenharmony_ci case AVMEDIA_TYPE_AUDIO : type = "audio" ; break; 824cabdff1aSopenharmony_ci case AVMEDIA_TYPE_SUBTITLE: type = "text" ; break; 825cabdff1aSopenharmony_ci default : type = "application"; break; 826cabdff1aSopenharmony_ci } 827cabdff1aSopenharmony_ci 828cabdff1aSopenharmony_ci av_strlcatf(buff, size, "m=%s %d RTP/AVP %d\r\n", type, port, payload_type); 829cabdff1aSopenharmony_ci sdp_write_address(buff, size, dest_addr, dest_type, ttl); 830cabdff1aSopenharmony_ci if (p->bit_rate) { 831cabdff1aSopenharmony_ci av_strlcatf(buff, size, "b=AS:%"PRId64"\r\n", p->bit_rate / 1000); 832cabdff1aSopenharmony_ci } 833cabdff1aSopenharmony_ci 834cabdff1aSopenharmony_ci return sdp_write_media_attributes(buff, size, st, payload_type, fmt); 835cabdff1aSopenharmony_ci} 836cabdff1aSopenharmony_ci 837cabdff1aSopenharmony_ciint av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size) 838cabdff1aSopenharmony_ci{ 839cabdff1aSopenharmony_ci AVDictionaryEntry *title = av_dict_get(ac[0]->metadata, "title", NULL, 0); 840cabdff1aSopenharmony_ci struct sdp_session_level s = { 0 }; 841cabdff1aSopenharmony_ci int i, j, port, ttl, is_multicast, index = 0; 842cabdff1aSopenharmony_ci char dst[32], dst_type[5]; 843cabdff1aSopenharmony_ci 844cabdff1aSopenharmony_ci memset(buf, 0, size); 845cabdff1aSopenharmony_ci s.user = "-"; 846cabdff1aSopenharmony_ci s.src_addr = "127.0.0.1"; /* FIXME: Properly set this */ 847cabdff1aSopenharmony_ci s.src_type = "IP4"; 848cabdff1aSopenharmony_ci s.name = title ? title->value : "No Name"; 849cabdff1aSopenharmony_ci 850cabdff1aSopenharmony_ci port = 0; 851cabdff1aSopenharmony_ci ttl = 0; 852cabdff1aSopenharmony_ci if (n_files == 1) { 853cabdff1aSopenharmony_ci port = sdp_get_address(dst, sizeof(dst), &ttl, ac[0]->url ? ac[0]->url : ""); 854cabdff1aSopenharmony_ci is_multicast = resolve_destination(dst, sizeof(dst), dst_type, 855cabdff1aSopenharmony_ci sizeof(dst_type)); 856cabdff1aSopenharmony_ci if (!is_multicast) 857cabdff1aSopenharmony_ci ttl = 0; 858cabdff1aSopenharmony_ci if (dst[0]) { 859cabdff1aSopenharmony_ci s.dst_addr = dst; 860cabdff1aSopenharmony_ci s.dst_type = dst_type; 861cabdff1aSopenharmony_ci s.ttl = ttl; 862cabdff1aSopenharmony_ci if (!strcmp(dst_type, "IP6")) { 863cabdff1aSopenharmony_ci s.src_addr = "::1"; 864cabdff1aSopenharmony_ci s.src_type = "IP6"; 865cabdff1aSopenharmony_ci } 866cabdff1aSopenharmony_ci } 867cabdff1aSopenharmony_ci } 868cabdff1aSopenharmony_ci sdp_write_header(buf, size, &s); 869cabdff1aSopenharmony_ci 870cabdff1aSopenharmony_ci dst[0] = 0; 871cabdff1aSopenharmony_ci for (i = 0; i < n_files; i++) { 872cabdff1aSopenharmony_ci if (n_files != 1) { 873cabdff1aSopenharmony_ci port = sdp_get_address(dst, sizeof(dst), &ttl, ac[i]->url ? ac[i]->url : ""); 874cabdff1aSopenharmony_ci is_multicast = resolve_destination(dst, sizeof(dst), dst_type, 875cabdff1aSopenharmony_ci sizeof(dst_type)); 876cabdff1aSopenharmony_ci if (!is_multicast) 877cabdff1aSopenharmony_ci ttl = 0; 878cabdff1aSopenharmony_ci } 879cabdff1aSopenharmony_ci for (j = 0; j < ac[i]->nb_streams; j++) { 880cabdff1aSopenharmony_ci int ret = ff_sdp_write_media(buf, size, ac[i]->streams[j], index++, 881cabdff1aSopenharmony_ci dst[0] ? dst : NULL, dst_type, 882cabdff1aSopenharmony_ci (port > 0) ? port + j * 2 : 0, 883cabdff1aSopenharmony_ci ttl, ac[i]); 884cabdff1aSopenharmony_ci if (ret < 0) 885cabdff1aSopenharmony_ci return ret; 886cabdff1aSopenharmony_ci 887cabdff1aSopenharmony_ci if (port <= 0) { 888cabdff1aSopenharmony_ci av_strlcatf(buf, size, 889cabdff1aSopenharmony_ci "a=control:streamid=%d\r\n", i + j); 890cabdff1aSopenharmony_ci } 891cabdff1aSopenharmony_ci if (ac[i]->pb && ac[i]->pb->av_class) { 892cabdff1aSopenharmony_ci uint8_t *crypto_suite = NULL, *crypto_params = NULL; 893cabdff1aSopenharmony_ci av_opt_get(ac[i]->pb, "srtp_out_suite", AV_OPT_SEARCH_CHILDREN, 894cabdff1aSopenharmony_ci &crypto_suite); 895cabdff1aSopenharmony_ci av_opt_get(ac[i]->pb, "srtp_out_params", AV_OPT_SEARCH_CHILDREN, 896cabdff1aSopenharmony_ci &crypto_params); 897cabdff1aSopenharmony_ci if (crypto_suite && crypto_suite[0]) 898cabdff1aSopenharmony_ci av_strlcatf(buf, size, 899cabdff1aSopenharmony_ci "a=crypto:1 %s inline:%s\r\n", 900cabdff1aSopenharmony_ci crypto_suite, crypto_params); 901cabdff1aSopenharmony_ci av_free(crypto_suite); 902cabdff1aSopenharmony_ci av_free(crypto_params); 903cabdff1aSopenharmony_ci } 904cabdff1aSopenharmony_ci } 905cabdff1aSopenharmony_ci } 906cabdff1aSopenharmony_ci 907cabdff1aSopenharmony_ci return 0; 908cabdff1aSopenharmony_ci} 909cabdff1aSopenharmony_ci#else 910cabdff1aSopenharmony_ciint av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size) 911cabdff1aSopenharmony_ci{ 912cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 913cabdff1aSopenharmony_ci} 914cabdff1aSopenharmony_ci 915cabdff1aSopenharmony_ciint ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx, 916cabdff1aSopenharmony_ci const char *dest_addr, const char *dest_type, 917cabdff1aSopenharmony_ci int port, int ttl, AVFormatContext *fmt) 918cabdff1aSopenharmony_ci{ 919cabdff1aSopenharmony_ci return AVERROR(ENOSYS); 920cabdff1aSopenharmony_ci} 921cabdff1aSopenharmony_ci#endif 922