1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * RTP H.264 Protocol (RFC3984) 3cabdff1aSopenharmony_ci * Copyright (c) 2006 Ryan Martell 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * @brief H.264 / RTP Code (RFC3984) 25cabdff1aSopenharmony_ci * @author Ryan Martell <rdm4@martellventures.com> 26cabdff1aSopenharmony_ci * 27cabdff1aSopenharmony_ci * @note Notes: 28cabdff1aSopenharmony_ci * Notes: 29cabdff1aSopenharmony_ci * This currently supports packetization mode: 30cabdff1aSopenharmony_ci * Single Nal Unit Mode (0), or 31cabdff1aSopenharmony_ci * Non-Interleaved Mode (1). It currently does not support 32cabdff1aSopenharmony_ci * Interleaved Mode (2). (This requires implementing STAP-B, MTAP16, MTAP24, 33cabdff1aSopenharmony_ci * FU-B packet types) 34cabdff1aSopenharmony_ci */ 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_ci#include "libavutil/attributes.h" 37cabdff1aSopenharmony_ci#include "libavutil/base64.h" 38cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 39cabdff1aSopenharmony_ci#include "libavutil/avstring.h" 40cabdff1aSopenharmony_ci#include "avformat.h" 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_ci#include "rtpdec.h" 43cabdff1aSopenharmony_ci#include "rtpdec_formats.h" 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_cistruct PayloadContext { 46cabdff1aSopenharmony_ci // sdp setup parameters 47cabdff1aSopenharmony_ci uint8_t profile_idc; 48cabdff1aSopenharmony_ci uint8_t profile_iop; 49cabdff1aSopenharmony_ci uint8_t level_idc; 50cabdff1aSopenharmony_ci int packetization_mode; 51cabdff1aSopenharmony_ci#ifdef DEBUG 52cabdff1aSopenharmony_ci int packet_types_received[32]; 53cabdff1aSopenharmony_ci#endif 54cabdff1aSopenharmony_ci}; 55cabdff1aSopenharmony_ci 56cabdff1aSopenharmony_ci#ifdef DEBUG 57cabdff1aSopenharmony_ci#define COUNT_NAL_TYPE(data, nal) data->packet_types_received[(nal) & 0x1f]++ 58cabdff1aSopenharmony_ci#define NAL_COUNTERS data->packet_types_received 59cabdff1aSopenharmony_ci#else 60cabdff1aSopenharmony_ci#define COUNT_NAL_TYPE(data, nal) do { } while (0) 61cabdff1aSopenharmony_ci#define NAL_COUNTERS NULL 62cabdff1aSopenharmony_ci#endif 63cabdff1aSopenharmony_ci#define NAL_MASK 0x1f 64cabdff1aSopenharmony_ci 65cabdff1aSopenharmony_cistatic const uint8_t start_sequence[] = { 0, 0, 0, 1 }; 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_cistatic void parse_profile_level_id(AVFormatContext *s, 68cabdff1aSopenharmony_ci PayloadContext *h264_data, 69cabdff1aSopenharmony_ci const char *value) 70cabdff1aSopenharmony_ci{ 71cabdff1aSopenharmony_ci char buffer[3]; 72cabdff1aSopenharmony_ci // 6 characters=3 bytes, in hex. 73cabdff1aSopenharmony_ci uint8_t profile_idc; 74cabdff1aSopenharmony_ci uint8_t profile_iop; 75cabdff1aSopenharmony_ci uint8_t level_idc; 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_ci buffer[0] = value[0]; 78cabdff1aSopenharmony_ci buffer[1] = value[1]; 79cabdff1aSopenharmony_ci buffer[2] = '\0'; 80cabdff1aSopenharmony_ci profile_idc = strtol(buffer, NULL, 16); 81cabdff1aSopenharmony_ci buffer[0] = value[2]; 82cabdff1aSopenharmony_ci buffer[1] = value[3]; 83cabdff1aSopenharmony_ci profile_iop = strtol(buffer, NULL, 16); 84cabdff1aSopenharmony_ci buffer[0] = value[4]; 85cabdff1aSopenharmony_ci buffer[1] = value[5]; 86cabdff1aSopenharmony_ci level_idc = strtol(buffer, NULL, 16); 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, 89cabdff1aSopenharmony_ci "RTP Profile IDC: %x Profile IOP: %x Level: %x\n", 90cabdff1aSopenharmony_ci profile_idc, profile_iop, level_idc); 91cabdff1aSopenharmony_ci h264_data->profile_idc = profile_idc; 92cabdff1aSopenharmony_ci h264_data->profile_iop = profile_iop; 93cabdff1aSopenharmony_ci h264_data->level_idc = level_idc; 94cabdff1aSopenharmony_ci} 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_ciint ff_h264_parse_sprop_parameter_sets(AVFormatContext *s, 97cabdff1aSopenharmony_ci uint8_t **data_ptr, int *size_ptr, 98cabdff1aSopenharmony_ci const char *value) 99cabdff1aSopenharmony_ci{ 100cabdff1aSopenharmony_ci char base64packet[1024]; 101cabdff1aSopenharmony_ci uint8_t decoded_packet[1024]; 102cabdff1aSopenharmony_ci int packet_size; 103cabdff1aSopenharmony_ci 104cabdff1aSopenharmony_ci while (*value) { 105cabdff1aSopenharmony_ci char *dst = base64packet; 106cabdff1aSopenharmony_ci 107cabdff1aSopenharmony_ci while (*value && *value != ',' 108cabdff1aSopenharmony_ci && (dst - base64packet) < sizeof(base64packet) - 1) { 109cabdff1aSopenharmony_ci *dst++ = *value++; 110cabdff1aSopenharmony_ci } 111cabdff1aSopenharmony_ci *dst++ = '\0'; 112cabdff1aSopenharmony_ci 113cabdff1aSopenharmony_ci if (*value == ',') 114cabdff1aSopenharmony_ci value++; 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_ci packet_size = av_base64_decode(decoded_packet, base64packet, 117cabdff1aSopenharmony_ci sizeof(decoded_packet)); 118cabdff1aSopenharmony_ci if (packet_size > 0) { 119cabdff1aSopenharmony_ci uint8_t *dest = av_realloc(*data_ptr, 120cabdff1aSopenharmony_ci packet_size + sizeof(start_sequence) + 121cabdff1aSopenharmony_ci *size_ptr + 122cabdff1aSopenharmony_ci AV_INPUT_BUFFER_PADDING_SIZE); 123cabdff1aSopenharmony_ci if (!dest) { 124cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, 125cabdff1aSopenharmony_ci "Unable to allocate memory for extradata!\n"); 126cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 127cabdff1aSopenharmony_ci } 128cabdff1aSopenharmony_ci *data_ptr = dest; 129cabdff1aSopenharmony_ci 130cabdff1aSopenharmony_ci memcpy(dest + *size_ptr, start_sequence, 131cabdff1aSopenharmony_ci sizeof(start_sequence)); 132cabdff1aSopenharmony_ci memcpy(dest + *size_ptr + sizeof(start_sequence), 133cabdff1aSopenharmony_ci decoded_packet, packet_size); 134cabdff1aSopenharmony_ci memset(dest + *size_ptr + sizeof(start_sequence) + 135cabdff1aSopenharmony_ci packet_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); 136cabdff1aSopenharmony_ci 137cabdff1aSopenharmony_ci *size_ptr += sizeof(start_sequence) + packet_size; 138cabdff1aSopenharmony_ci } 139cabdff1aSopenharmony_ci } 140cabdff1aSopenharmony_ci 141cabdff1aSopenharmony_ci return 0; 142cabdff1aSopenharmony_ci} 143cabdff1aSopenharmony_ci 144cabdff1aSopenharmony_cistatic int sdp_parse_fmtp_config_h264(AVFormatContext *s, 145cabdff1aSopenharmony_ci AVStream *stream, 146cabdff1aSopenharmony_ci PayloadContext *h264_data, 147cabdff1aSopenharmony_ci const char *attr, const char *value) 148cabdff1aSopenharmony_ci{ 149cabdff1aSopenharmony_ci AVCodecParameters *par = stream->codecpar; 150cabdff1aSopenharmony_ci 151cabdff1aSopenharmony_ci if (!strcmp(attr, "packetization-mode")) { 152cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "RTP Packetization Mode: %d\n", atoi(value)); 153cabdff1aSopenharmony_ci h264_data->packetization_mode = atoi(value); 154cabdff1aSopenharmony_ci /* 155cabdff1aSopenharmony_ci * Packetization Mode: 156cabdff1aSopenharmony_ci * 0 or not present: Single NAL mode (Only nals from 1-23 are allowed) 157cabdff1aSopenharmony_ci * 1: Non-interleaved Mode: 1-23, 24 (STAP-A), 28 (FU-A) are allowed. 158cabdff1aSopenharmony_ci * 2: Interleaved Mode: 25 (STAP-B), 26 (MTAP16), 27 (MTAP24), 28 (FU-A), 159cabdff1aSopenharmony_ci * and 29 (FU-B) are allowed. 160cabdff1aSopenharmony_ci */ 161cabdff1aSopenharmony_ci if (h264_data->packetization_mode > 1) 162cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, 163cabdff1aSopenharmony_ci "Interleaved RTP mode is not supported yet.\n"); 164cabdff1aSopenharmony_ci } else if (!strcmp(attr, "profile-level-id")) { 165cabdff1aSopenharmony_ci if (strlen(value) == 6) 166cabdff1aSopenharmony_ci parse_profile_level_id(s, h264_data, value); 167cabdff1aSopenharmony_ci } else if (!strcmp(attr, "sprop-parameter-sets")) { 168cabdff1aSopenharmony_ci int ret; 169cabdff1aSopenharmony_ci if (*value == 0 || value[strlen(value) - 1] == ',') { 170cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "Missing PPS in sprop-parameter-sets, ignoring\n"); 171cabdff1aSopenharmony_ci return 0; 172cabdff1aSopenharmony_ci } 173cabdff1aSopenharmony_ci par->extradata_size = 0; 174cabdff1aSopenharmony_ci av_freep(&par->extradata); 175cabdff1aSopenharmony_ci ret = ff_h264_parse_sprop_parameter_sets(s, &par->extradata, 176cabdff1aSopenharmony_ci &par->extradata_size, value); 177cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "Extradata set to %p (size: %d)\n", 178cabdff1aSopenharmony_ci par->extradata, par->extradata_size); 179cabdff1aSopenharmony_ci return ret; 180cabdff1aSopenharmony_ci } 181cabdff1aSopenharmony_ci return 0; 182cabdff1aSopenharmony_ci} 183cabdff1aSopenharmony_ci 184cabdff1aSopenharmony_civoid ff_h264_parse_framesize(AVCodecParameters *par, const char *p) 185cabdff1aSopenharmony_ci{ 186cabdff1aSopenharmony_ci char buf1[50]; 187cabdff1aSopenharmony_ci char *dst = buf1; 188cabdff1aSopenharmony_ci 189cabdff1aSopenharmony_ci // remove the protocol identifier 190cabdff1aSopenharmony_ci while (*p && *p == ' ') 191cabdff1aSopenharmony_ci p++; // strip spaces. 192cabdff1aSopenharmony_ci while (*p && *p != ' ') 193cabdff1aSopenharmony_ci p++; // eat protocol identifier 194cabdff1aSopenharmony_ci while (*p && *p == ' ') 195cabdff1aSopenharmony_ci p++; // strip trailing spaces. 196cabdff1aSopenharmony_ci while (*p && *p != '-' && (dst - buf1) < sizeof(buf1) - 1) 197cabdff1aSopenharmony_ci *dst++ = *p++; 198cabdff1aSopenharmony_ci *dst = '\0'; 199cabdff1aSopenharmony_ci 200cabdff1aSopenharmony_ci // a='framesize:96 320-240' 201cabdff1aSopenharmony_ci // set our parameters 202cabdff1aSopenharmony_ci par->width = atoi(buf1); 203cabdff1aSopenharmony_ci par->height = atoi(p + 1); // skip the - 204cabdff1aSopenharmony_ci} 205cabdff1aSopenharmony_ci 206cabdff1aSopenharmony_ciint ff_h264_handle_aggregated_packet(AVFormatContext *ctx, PayloadContext *data, AVPacket *pkt, 207cabdff1aSopenharmony_ci const uint8_t *buf, int len, 208cabdff1aSopenharmony_ci int skip_between, int *nal_counters, 209cabdff1aSopenharmony_ci int nal_mask) 210cabdff1aSopenharmony_ci{ 211cabdff1aSopenharmony_ci int pass = 0; 212cabdff1aSopenharmony_ci int total_length = 0; 213cabdff1aSopenharmony_ci uint8_t *dst = NULL; 214cabdff1aSopenharmony_ci int ret; 215cabdff1aSopenharmony_ci 216cabdff1aSopenharmony_ci // first we are going to figure out the total size 217cabdff1aSopenharmony_ci for (pass = 0; pass < 2; pass++) { 218cabdff1aSopenharmony_ci const uint8_t *src = buf; 219cabdff1aSopenharmony_ci int src_len = len; 220cabdff1aSopenharmony_ci 221cabdff1aSopenharmony_ci while (src_len > 2) { 222cabdff1aSopenharmony_ci uint16_t nal_size = AV_RB16(src); 223cabdff1aSopenharmony_ci 224cabdff1aSopenharmony_ci // consume the length of the aggregate 225cabdff1aSopenharmony_ci src += 2; 226cabdff1aSopenharmony_ci src_len -= 2; 227cabdff1aSopenharmony_ci 228cabdff1aSopenharmony_ci if (nal_size <= src_len) { 229cabdff1aSopenharmony_ci if (pass == 0) { 230cabdff1aSopenharmony_ci // counting 231cabdff1aSopenharmony_ci total_length += sizeof(start_sequence) + nal_size; 232cabdff1aSopenharmony_ci } else { 233cabdff1aSopenharmony_ci // copying 234cabdff1aSopenharmony_ci memcpy(dst, start_sequence, sizeof(start_sequence)); 235cabdff1aSopenharmony_ci dst += sizeof(start_sequence); 236cabdff1aSopenharmony_ci memcpy(dst, src, nal_size); 237cabdff1aSopenharmony_ci if (nal_counters) 238cabdff1aSopenharmony_ci nal_counters[(*src) & nal_mask]++; 239cabdff1aSopenharmony_ci dst += nal_size; 240cabdff1aSopenharmony_ci } 241cabdff1aSopenharmony_ci } else { 242cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, 243cabdff1aSopenharmony_ci "nal size exceeds length: %d %d\n", nal_size, src_len); 244cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 245cabdff1aSopenharmony_ci } 246cabdff1aSopenharmony_ci 247cabdff1aSopenharmony_ci // eat what we handled 248cabdff1aSopenharmony_ci src += nal_size + skip_between; 249cabdff1aSopenharmony_ci src_len -= nal_size + skip_between; 250cabdff1aSopenharmony_ci } 251cabdff1aSopenharmony_ci 252cabdff1aSopenharmony_ci if (pass == 0) { 253cabdff1aSopenharmony_ci /* now we know the total size of the packet (with the 254cabdff1aSopenharmony_ci * start sequences added) */ 255cabdff1aSopenharmony_ci if ((ret = av_new_packet(pkt, total_length)) < 0) 256cabdff1aSopenharmony_ci return ret; 257cabdff1aSopenharmony_ci dst = pkt->data; 258cabdff1aSopenharmony_ci } 259cabdff1aSopenharmony_ci } 260cabdff1aSopenharmony_ci 261cabdff1aSopenharmony_ci return 0; 262cabdff1aSopenharmony_ci} 263cabdff1aSopenharmony_ci 264cabdff1aSopenharmony_ciint ff_h264_handle_frag_packet(AVPacket *pkt, const uint8_t *buf, int len, 265cabdff1aSopenharmony_ci int start_bit, const uint8_t *nal_header, 266cabdff1aSopenharmony_ci int nal_header_len) 267cabdff1aSopenharmony_ci{ 268cabdff1aSopenharmony_ci int ret; 269cabdff1aSopenharmony_ci int tot_len = len; 270cabdff1aSopenharmony_ci int pos = 0; 271cabdff1aSopenharmony_ci if (start_bit) 272cabdff1aSopenharmony_ci tot_len += sizeof(start_sequence) + nal_header_len; 273cabdff1aSopenharmony_ci if ((ret = av_new_packet(pkt, tot_len)) < 0) 274cabdff1aSopenharmony_ci return ret; 275cabdff1aSopenharmony_ci if (start_bit) { 276cabdff1aSopenharmony_ci memcpy(pkt->data + pos, start_sequence, sizeof(start_sequence)); 277cabdff1aSopenharmony_ci pos += sizeof(start_sequence); 278cabdff1aSopenharmony_ci memcpy(pkt->data + pos, nal_header, nal_header_len); 279cabdff1aSopenharmony_ci pos += nal_header_len; 280cabdff1aSopenharmony_ci } 281cabdff1aSopenharmony_ci memcpy(pkt->data + pos, buf, len); 282cabdff1aSopenharmony_ci return 0; 283cabdff1aSopenharmony_ci} 284cabdff1aSopenharmony_ci 285cabdff1aSopenharmony_cistatic int h264_handle_packet_fu_a(AVFormatContext *ctx, PayloadContext *data, AVPacket *pkt, 286cabdff1aSopenharmony_ci const uint8_t *buf, int len, 287cabdff1aSopenharmony_ci int *nal_counters, int nal_mask) 288cabdff1aSopenharmony_ci{ 289cabdff1aSopenharmony_ci uint8_t fu_indicator, fu_header, start_bit, nal_type, nal; 290cabdff1aSopenharmony_ci 291cabdff1aSopenharmony_ci if (len < 3) { 292cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Too short data for FU-A H.264 RTP packet\n"); 293cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 294cabdff1aSopenharmony_ci } 295cabdff1aSopenharmony_ci 296cabdff1aSopenharmony_ci fu_indicator = buf[0]; 297cabdff1aSopenharmony_ci fu_header = buf[1]; 298cabdff1aSopenharmony_ci start_bit = fu_header >> 7; 299cabdff1aSopenharmony_ci nal_type = fu_header & 0x1f; 300cabdff1aSopenharmony_ci nal = fu_indicator & 0xe0 | nal_type; 301cabdff1aSopenharmony_ci 302cabdff1aSopenharmony_ci // skip the fu_indicator and fu_header 303cabdff1aSopenharmony_ci buf += 2; 304cabdff1aSopenharmony_ci len -= 2; 305cabdff1aSopenharmony_ci 306cabdff1aSopenharmony_ci if (start_bit && nal_counters) 307cabdff1aSopenharmony_ci nal_counters[nal_type & nal_mask]++; 308cabdff1aSopenharmony_ci return ff_h264_handle_frag_packet(pkt, buf, len, start_bit, &nal, 1); 309cabdff1aSopenharmony_ci} 310cabdff1aSopenharmony_ci 311cabdff1aSopenharmony_ci// return 0 on packet, no more left, 1 on packet, 1 on partial packet 312cabdff1aSopenharmony_cistatic int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data, 313cabdff1aSopenharmony_ci AVStream *st, AVPacket *pkt, uint32_t *timestamp, 314cabdff1aSopenharmony_ci const uint8_t *buf, int len, uint16_t seq, 315cabdff1aSopenharmony_ci int flags) 316cabdff1aSopenharmony_ci{ 317cabdff1aSopenharmony_ci uint8_t nal; 318cabdff1aSopenharmony_ci uint8_t type; 319cabdff1aSopenharmony_ci int result = 0; 320cabdff1aSopenharmony_ci 321cabdff1aSopenharmony_ci if (!len) { 322cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Empty H.264 RTP packet\n"); 323cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 324cabdff1aSopenharmony_ci } 325cabdff1aSopenharmony_ci nal = buf[0]; 326cabdff1aSopenharmony_ci type = nal & 0x1f; 327cabdff1aSopenharmony_ci 328cabdff1aSopenharmony_ci /* Simplify the case (these are all the NAL types used internally by 329cabdff1aSopenharmony_ci * the H.264 codec). */ 330cabdff1aSopenharmony_ci if (type >= 1 && type <= 23) 331cabdff1aSopenharmony_ci type = 1; 332cabdff1aSopenharmony_ci switch (type) { 333cabdff1aSopenharmony_ci case 0: // undefined, but pass them through 334cabdff1aSopenharmony_ci case 1: 335cabdff1aSopenharmony_ci if ((result = av_new_packet(pkt, len + sizeof(start_sequence))) < 0) 336cabdff1aSopenharmony_ci return result; 337cabdff1aSopenharmony_ci memcpy(pkt->data, start_sequence, sizeof(start_sequence)); 338cabdff1aSopenharmony_ci memcpy(pkt->data + sizeof(start_sequence), buf, len); 339cabdff1aSopenharmony_ci COUNT_NAL_TYPE(data, nal); 340cabdff1aSopenharmony_ci break; 341cabdff1aSopenharmony_ci 342cabdff1aSopenharmony_ci case 24: // STAP-A (one packet, multiple nals) 343cabdff1aSopenharmony_ci // consume the STAP-A NAL 344cabdff1aSopenharmony_ci buf++; 345cabdff1aSopenharmony_ci len--; 346cabdff1aSopenharmony_ci result = ff_h264_handle_aggregated_packet(ctx, data, pkt, buf, len, 0, 347cabdff1aSopenharmony_ci NAL_COUNTERS, NAL_MASK); 348cabdff1aSopenharmony_ci break; 349cabdff1aSopenharmony_ci 350cabdff1aSopenharmony_ci case 25: // STAP-B 351cabdff1aSopenharmony_ci case 26: // MTAP-16 352cabdff1aSopenharmony_ci case 27: // MTAP-24 353cabdff1aSopenharmony_ci case 29: // FU-B 354cabdff1aSopenharmony_ci avpriv_report_missing_feature(ctx, "RTP H.264 NAL unit type %d", type); 355cabdff1aSopenharmony_ci result = AVERROR_PATCHWELCOME; 356cabdff1aSopenharmony_ci break; 357cabdff1aSopenharmony_ci 358cabdff1aSopenharmony_ci case 28: // FU-A (fragmented nal) 359cabdff1aSopenharmony_ci result = h264_handle_packet_fu_a(ctx, data, pkt, buf, len, 360cabdff1aSopenharmony_ci NAL_COUNTERS, NAL_MASK); 361cabdff1aSopenharmony_ci break; 362cabdff1aSopenharmony_ci 363cabdff1aSopenharmony_ci case 30: // undefined 364cabdff1aSopenharmony_ci case 31: // undefined 365cabdff1aSopenharmony_ci default: 366cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Undefined type (%d)\n", type); 367cabdff1aSopenharmony_ci result = AVERROR_INVALIDDATA; 368cabdff1aSopenharmony_ci break; 369cabdff1aSopenharmony_ci } 370cabdff1aSopenharmony_ci 371cabdff1aSopenharmony_ci pkt->stream_index = st->index; 372cabdff1aSopenharmony_ci 373cabdff1aSopenharmony_ci return result; 374cabdff1aSopenharmony_ci} 375cabdff1aSopenharmony_ci 376cabdff1aSopenharmony_cistatic void h264_close_context(PayloadContext *data) 377cabdff1aSopenharmony_ci{ 378cabdff1aSopenharmony_ci#ifdef DEBUG 379cabdff1aSopenharmony_ci int ii; 380cabdff1aSopenharmony_ci 381cabdff1aSopenharmony_ci for (ii = 0; ii < 32; ii++) { 382cabdff1aSopenharmony_ci if (data->packet_types_received[ii]) 383cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_DEBUG, "Received %d packets of type %d\n", 384cabdff1aSopenharmony_ci data->packet_types_received[ii], ii); 385cabdff1aSopenharmony_ci } 386cabdff1aSopenharmony_ci#endif 387cabdff1aSopenharmony_ci} 388cabdff1aSopenharmony_ci 389cabdff1aSopenharmony_cistatic int parse_h264_sdp_line(AVFormatContext *s, int st_index, 390cabdff1aSopenharmony_ci PayloadContext *h264_data, const char *line) 391cabdff1aSopenharmony_ci{ 392cabdff1aSopenharmony_ci AVStream *stream; 393cabdff1aSopenharmony_ci const char *p = line; 394cabdff1aSopenharmony_ci 395cabdff1aSopenharmony_ci if (st_index < 0) 396cabdff1aSopenharmony_ci return 0; 397cabdff1aSopenharmony_ci 398cabdff1aSopenharmony_ci stream = s->streams[st_index]; 399cabdff1aSopenharmony_ci 400cabdff1aSopenharmony_ci if (av_strstart(p, "framesize:", &p)) { 401cabdff1aSopenharmony_ci ff_h264_parse_framesize(stream->codecpar, p); 402cabdff1aSopenharmony_ci } else if (av_strstart(p, "fmtp:", &p)) { 403cabdff1aSopenharmony_ci return ff_parse_fmtp(s, stream, h264_data, p, sdp_parse_fmtp_config_h264); 404cabdff1aSopenharmony_ci } else if (av_strstart(p, "cliprect:", &p)) { 405cabdff1aSopenharmony_ci // could use this if we wanted. 406cabdff1aSopenharmony_ci } 407cabdff1aSopenharmony_ci 408cabdff1aSopenharmony_ci return 0; 409cabdff1aSopenharmony_ci} 410cabdff1aSopenharmony_ci 411cabdff1aSopenharmony_ciconst RTPDynamicProtocolHandler ff_h264_dynamic_handler = { 412cabdff1aSopenharmony_ci .enc_name = "H264", 413cabdff1aSopenharmony_ci .codec_type = AVMEDIA_TYPE_VIDEO, 414cabdff1aSopenharmony_ci .codec_id = AV_CODEC_ID_H264, 415cabdff1aSopenharmony_ci .need_parsing = AVSTREAM_PARSE_FULL, 416cabdff1aSopenharmony_ci .priv_data_size = sizeof(PayloadContext), 417cabdff1aSopenharmony_ci .parse_sdp_a_line = parse_h264_sdp_line, 418cabdff1aSopenharmony_ci .close = h264_close_context, 419cabdff1aSopenharmony_ci .parse_packet = h264_handle_packet, 420cabdff1aSopenharmony_ci}; 421