1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * RTP Depacketization of MP4A-LATM, RFC 3016 3cabdff1aSopenharmony_ci * Copyright (c) 2010 Martin Storsjo 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#include "avio_internal.h" 23cabdff1aSopenharmony_ci#include "rtpdec_formats.h" 24cabdff1aSopenharmony_ci#include "internal.h" 25cabdff1aSopenharmony_ci#include "libavutil/avstring.h" 26cabdff1aSopenharmony_ci#include "libavcodec/get_bits.h" 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_cistruct PayloadContext { 29cabdff1aSopenharmony_ci AVIOContext *dyn_buf; 30cabdff1aSopenharmony_ci uint8_t *buf; 31cabdff1aSopenharmony_ci int pos, len; 32cabdff1aSopenharmony_ci uint32_t timestamp; 33cabdff1aSopenharmony_ci}; 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_cistatic void latm_close_context(PayloadContext *data) 36cabdff1aSopenharmony_ci{ 37cabdff1aSopenharmony_ci ffio_free_dyn_buf(&data->dyn_buf); 38cabdff1aSopenharmony_ci av_freep(&data->buf); 39cabdff1aSopenharmony_ci} 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_cistatic int latm_parse_packet(AVFormatContext *ctx, PayloadContext *data, 42cabdff1aSopenharmony_ci AVStream *st, AVPacket *pkt, uint32_t *timestamp, 43cabdff1aSopenharmony_ci const uint8_t *buf, int len, uint16_t seq, 44cabdff1aSopenharmony_ci int flags) 45cabdff1aSopenharmony_ci{ 46cabdff1aSopenharmony_ci int ret, cur_len; 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci if (buf) { 49cabdff1aSopenharmony_ci if (!data->dyn_buf || data->timestamp != *timestamp) { 50cabdff1aSopenharmony_ci av_freep(&data->buf); 51cabdff1aSopenharmony_ci ffio_free_dyn_buf(&data->dyn_buf); 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_ci data->timestamp = *timestamp; 54cabdff1aSopenharmony_ci if ((ret = avio_open_dyn_buf(&data->dyn_buf)) < 0) 55cabdff1aSopenharmony_ci return ret; 56cabdff1aSopenharmony_ci } 57cabdff1aSopenharmony_ci avio_write(data->dyn_buf, buf, len); 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_ci if (!(flags & RTP_FLAG_MARKER)) 60cabdff1aSopenharmony_ci return AVERROR(EAGAIN); 61cabdff1aSopenharmony_ci av_freep(&data->buf); 62cabdff1aSopenharmony_ci data->len = avio_close_dyn_buf(data->dyn_buf, &data->buf); 63cabdff1aSopenharmony_ci data->dyn_buf = NULL; 64cabdff1aSopenharmony_ci data->pos = 0; 65cabdff1aSopenharmony_ci } 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_ci if (!data->buf) { 68cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "No data available yet\n"); 69cabdff1aSopenharmony_ci return AVERROR(EIO); 70cabdff1aSopenharmony_ci } 71cabdff1aSopenharmony_ci 72cabdff1aSopenharmony_ci cur_len = 0; 73cabdff1aSopenharmony_ci while (data->pos < data->len) { 74cabdff1aSopenharmony_ci uint8_t val = data->buf[data->pos++]; 75cabdff1aSopenharmony_ci cur_len += val; 76cabdff1aSopenharmony_ci if (val != 0xff) 77cabdff1aSopenharmony_ci break; 78cabdff1aSopenharmony_ci } 79cabdff1aSopenharmony_ci if (data->pos + cur_len > data->len) { 80cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Malformed LATM packet\n"); 81cabdff1aSopenharmony_ci return AVERROR(EIO); 82cabdff1aSopenharmony_ci } 83cabdff1aSopenharmony_ci 84cabdff1aSopenharmony_ci if ((ret = av_new_packet(pkt, cur_len)) < 0) 85cabdff1aSopenharmony_ci return ret; 86cabdff1aSopenharmony_ci memcpy(pkt->data, data->buf + data->pos, cur_len); 87cabdff1aSopenharmony_ci data->pos += cur_len; 88cabdff1aSopenharmony_ci pkt->stream_index = st->index; 89cabdff1aSopenharmony_ci return data->pos < data->len; 90cabdff1aSopenharmony_ci} 91cabdff1aSopenharmony_ci 92cabdff1aSopenharmony_cistatic int parse_fmtp_config(AVStream *st, const char *value) 93cabdff1aSopenharmony_ci{ 94cabdff1aSopenharmony_ci int len = ff_hex_to_data(NULL, value), i, ret = 0; 95cabdff1aSopenharmony_ci GetBitContext gb; 96cabdff1aSopenharmony_ci uint8_t *config; 97cabdff1aSopenharmony_ci int audio_mux_version, same_time_framing, num_programs, num_layers; 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_ci /* Pad this buffer, too, to avoid out of bounds reads with get_bits below */ 100cabdff1aSopenharmony_ci config = av_mallocz(len + AV_INPUT_BUFFER_PADDING_SIZE); 101cabdff1aSopenharmony_ci if (!config) 102cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 103cabdff1aSopenharmony_ci ff_hex_to_data(config, value); 104cabdff1aSopenharmony_ci ret = init_get_bits(&gb, config, len*8); 105cabdff1aSopenharmony_ci if (ret < 0) 106cabdff1aSopenharmony_ci return ret; 107cabdff1aSopenharmony_ci audio_mux_version = get_bits(&gb, 1); 108cabdff1aSopenharmony_ci same_time_framing = get_bits(&gb, 1); 109cabdff1aSopenharmony_ci skip_bits(&gb, 6); /* num_sub_frames */ 110cabdff1aSopenharmony_ci num_programs = get_bits(&gb, 4); 111cabdff1aSopenharmony_ci num_layers = get_bits(&gb, 3); 112cabdff1aSopenharmony_ci if (audio_mux_version != 0 || same_time_framing != 1 || num_programs != 0 || 113cabdff1aSopenharmony_ci num_layers != 0) { 114cabdff1aSopenharmony_ci avpriv_report_missing_feature(NULL, "LATM config (%d,%d,%d,%d)", 115cabdff1aSopenharmony_ci audio_mux_version, same_time_framing, 116cabdff1aSopenharmony_ci num_programs, num_layers); 117cabdff1aSopenharmony_ci ret = AVERROR_PATCHWELCOME; 118cabdff1aSopenharmony_ci goto end; 119cabdff1aSopenharmony_ci } 120cabdff1aSopenharmony_ci ret = ff_alloc_extradata(st->codecpar, (get_bits_left(&gb) + 7)/8); 121cabdff1aSopenharmony_ci if (ret < 0) { 122cabdff1aSopenharmony_ci goto end; 123cabdff1aSopenharmony_ci } 124cabdff1aSopenharmony_ci for (i = 0; i < st->codecpar->extradata_size; i++) 125cabdff1aSopenharmony_ci st->codecpar->extradata[i] = get_bits(&gb, 8); 126cabdff1aSopenharmony_ci 127cabdff1aSopenharmony_ciend: 128cabdff1aSopenharmony_ci av_free(config); 129cabdff1aSopenharmony_ci return ret; 130cabdff1aSopenharmony_ci} 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_cistatic int parse_fmtp(AVFormatContext *s, 133cabdff1aSopenharmony_ci AVStream *stream, PayloadContext *data, 134cabdff1aSopenharmony_ci const char *attr, const char *value) 135cabdff1aSopenharmony_ci{ 136cabdff1aSopenharmony_ci int res; 137cabdff1aSopenharmony_ci 138cabdff1aSopenharmony_ci if (!strcmp(attr, "config")) { 139cabdff1aSopenharmony_ci res = parse_fmtp_config(stream, value); 140cabdff1aSopenharmony_ci if (res < 0) 141cabdff1aSopenharmony_ci return res; 142cabdff1aSopenharmony_ci } else if (!strcmp(attr, "cpresent")) { 143cabdff1aSopenharmony_ci int cpresent = atoi(value); 144cabdff1aSopenharmony_ci if (cpresent != 0) 145cabdff1aSopenharmony_ci avpriv_request_sample(s, 146cabdff1aSopenharmony_ci "RTP MP4A-LATM with in-band configuration"); 147cabdff1aSopenharmony_ci } 148cabdff1aSopenharmony_ci 149cabdff1aSopenharmony_ci return 0; 150cabdff1aSopenharmony_ci} 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_cistatic int latm_parse_sdp_line(AVFormatContext *s, int st_index, 153cabdff1aSopenharmony_ci PayloadContext *data, const char *line) 154cabdff1aSopenharmony_ci{ 155cabdff1aSopenharmony_ci const char *p; 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_ci if (st_index < 0) 158cabdff1aSopenharmony_ci return 0; 159cabdff1aSopenharmony_ci 160cabdff1aSopenharmony_ci if (av_strstart(line, "fmtp:", &p)) 161cabdff1aSopenharmony_ci return ff_parse_fmtp(s, s->streams[st_index], data, p, parse_fmtp); 162cabdff1aSopenharmony_ci 163cabdff1aSopenharmony_ci return 0; 164cabdff1aSopenharmony_ci} 165cabdff1aSopenharmony_ci 166cabdff1aSopenharmony_ciconst RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler = { 167cabdff1aSopenharmony_ci .enc_name = "MP4A-LATM", 168cabdff1aSopenharmony_ci .codec_type = AVMEDIA_TYPE_AUDIO, 169cabdff1aSopenharmony_ci .codec_id = AV_CODEC_ID_AAC, 170cabdff1aSopenharmony_ci .priv_data_size = sizeof(PayloadContext), 171cabdff1aSopenharmony_ci .parse_sdp_a_line = latm_parse_sdp_line, 172cabdff1aSopenharmony_ci .close = latm_close_context, 173cabdff1aSopenharmony_ci .parse_packet = latm_parse_packet, 174cabdff1aSopenharmony_ci}; 175