1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * RTP parser for AC3 payload format (RFC 4184) 3cabdff1aSopenharmony_ci * Copyright (c) 2015 Gilles Chanteperdrix <gch@xenomai.org> 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 "avformat.h" 23cabdff1aSopenharmony_ci#include "avio_internal.h" 24cabdff1aSopenharmony_ci#include "rtpdec_formats.h" 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci#define RTP_AC3_PAYLOAD_HEADER_SIZE 2 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_cistruct PayloadContext { 29cabdff1aSopenharmony_ci unsigned nr_frames; 30cabdff1aSopenharmony_ci unsigned last_frame; 31cabdff1aSopenharmony_ci uint32_t timestamp; 32cabdff1aSopenharmony_ci AVIOContext *fragment; 33cabdff1aSopenharmony_ci}; 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_cistatic void ac3_close_context(PayloadContext *data) 36cabdff1aSopenharmony_ci{ 37cabdff1aSopenharmony_ci ffio_free_dyn_buf(&data->fragment); 38cabdff1aSopenharmony_ci} 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_cistatic int ac3_handle_packet(AVFormatContext *ctx, PayloadContext *data, 41cabdff1aSopenharmony_ci AVStream *st, AVPacket *pkt, uint32_t *timestamp, 42cabdff1aSopenharmony_ci const uint8_t *buf, int len, uint16_t seq, 43cabdff1aSopenharmony_ci int flags) 44cabdff1aSopenharmony_ci{ 45cabdff1aSopenharmony_ci unsigned frame_type; 46cabdff1aSopenharmony_ci unsigned nr_frames; 47cabdff1aSopenharmony_ci int err; 48cabdff1aSopenharmony_ci 49cabdff1aSopenharmony_ci if (len < RTP_AC3_PAYLOAD_HEADER_SIZE + 1) { 50cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Invalid %d bytes packet\n", len); 51cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 52cabdff1aSopenharmony_ci } 53cabdff1aSopenharmony_ci 54cabdff1aSopenharmony_ci frame_type = buf[0] & 0x3; 55cabdff1aSopenharmony_ci nr_frames = buf[1]; 56cabdff1aSopenharmony_ci buf += RTP_AC3_PAYLOAD_HEADER_SIZE; 57cabdff1aSopenharmony_ci len -= RTP_AC3_PAYLOAD_HEADER_SIZE; 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_ci switch (frame_type) { 60cabdff1aSopenharmony_ci case 0: /* One or more complete frames */ 61cabdff1aSopenharmony_ci if (!nr_frames) { 62cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Invalid AC3 packet data\n"); 63cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 64cabdff1aSopenharmony_ci } 65cabdff1aSopenharmony_ci if ((err = av_new_packet(pkt, len)) < 0) { 66cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Out of memory.\n"); 67cabdff1aSopenharmony_ci return err; 68cabdff1aSopenharmony_ci } 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci pkt->stream_index = st->index; 71cabdff1aSopenharmony_ci memcpy(pkt->data, buf, len); 72cabdff1aSopenharmony_ci return 0; 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci case 1: 75cabdff1aSopenharmony_ci case 2: /* First fragment */ 76cabdff1aSopenharmony_ci ffio_free_dyn_buf(&data->fragment); 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_ci data->last_frame = 1; 79cabdff1aSopenharmony_ci data->nr_frames = nr_frames; 80cabdff1aSopenharmony_ci err = avio_open_dyn_buf(&data->fragment); 81cabdff1aSopenharmony_ci if (err < 0) 82cabdff1aSopenharmony_ci return err; 83cabdff1aSopenharmony_ci 84cabdff1aSopenharmony_ci avio_write(data->fragment, buf, len); 85cabdff1aSopenharmony_ci data->timestamp = *timestamp; 86cabdff1aSopenharmony_ci return AVERROR(EAGAIN); 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci case 3: /* Fragment other than first */ 89cabdff1aSopenharmony_ci if (!data->fragment) { 90cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_WARNING, 91cabdff1aSopenharmony_ci "Received packet without a start fragment; dropping.\n"); 92cabdff1aSopenharmony_ci return AVERROR(EAGAIN); 93cabdff1aSopenharmony_ci } 94cabdff1aSopenharmony_ci if (nr_frames != data->nr_frames || 95cabdff1aSopenharmony_ci data->timestamp != *timestamp) { 96cabdff1aSopenharmony_ci ffio_free_dyn_buf(&data->fragment); 97cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Invalid packet received\n"); 98cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 99cabdff1aSopenharmony_ci } 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_ci avio_write(data->fragment, buf, len); 102cabdff1aSopenharmony_ci data->last_frame++; 103cabdff1aSopenharmony_ci } 104cabdff1aSopenharmony_ci 105cabdff1aSopenharmony_ci if (!(flags & RTP_FLAG_MARKER)) 106cabdff1aSopenharmony_ci return AVERROR(EAGAIN); 107cabdff1aSopenharmony_ci 108cabdff1aSopenharmony_ci if (data->last_frame != data->nr_frames) { 109cabdff1aSopenharmony_ci ffio_free_dyn_buf(&data->fragment); 110cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Missed %d packets\n", 111cabdff1aSopenharmony_ci data->nr_frames - data->last_frame); 112cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 113cabdff1aSopenharmony_ci } 114cabdff1aSopenharmony_ci 115cabdff1aSopenharmony_ci err = ff_rtp_finalize_packet(pkt, &data->fragment, st->index); 116cabdff1aSopenharmony_ci if (err < 0) { 117cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, 118cabdff1aSopenharmony_ci "Error occurred when getting fragment buffer.\n"); 119cabdff1aSopenharmony_ci return err; 120cabdff1aSopenharmony_ci } 121cabdff1aSopenharmony_ci 122cabdff1aSopenharmony_ci return 0; 123cabdff1aSopenharmony_ci} 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ciconst RTPDynamicProtocolHandler ff_ac3_dynamic_handler = { 126cabdff1aSopenharmony_ci .enc_name = "ac3", 127cabdff1aSopenharmony_ci .codec_type = AVMEDIA_TYPE_AUDIO, 128cabdff1aSopenharmony_ci .codec_id = AV_CODEC_ID_AC3, 129cabdff1aSopenharmony_ci .need_parsing = AVSTREAM_PARSE_FULL, 130cabdff1aSopenharmony_ci .priv_data_size = sizeof(PayloadContext), 131cabdff1aSopenharmony_ci .close = ac3_close_context, 132cabdff1aSopenharmony_ci .parse_packet = ac3_handle_packet, 133cabdff1aSopenharmony_ci}; 134