From 73e6c53e64836ef89532a98caae0f6d00027cd61 Mon Sep 17 00:00:00 2001 From: Josh Allmann Date: Fri, 25 Jun 2010 08:01:20 +0000 Subject: rtpdec: Move AAC depacketization code in rtpdec to a proper payload handler Patch by Josh Allmann, joshua dot allmann at gmail Originally committed as revision 23771 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/rtpdec_mpeg4.c | 84 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) (limited to 'libavformat/rtpdec_mpeg4.c') diff --git a/libavformat/rtpdec_mpeg4.c b/libavformat/rtpdec_mpeg4.c index b301444e2c..8a94d6ed41 100644 --- a/libavformat/rtpdec_mpeg4.c +++ b/libavformat/rtpdec_mpeg4.c @@ -30,6 +30,7 @@ #include "rtpdec_mpeg4.h" #include "internal.h" #include "libavutil/avstring.h" +#include "libavcodec/get_bits.h" #include #include "rtsp.h" //XXX remove this dependency @@ -103,6 +104,87 @@ static int parse_fmtp_config(AVCodecContext * codec, char *value) return 0; } +static int rtp_parse_mp4_au(RTSPStream *rtsp_st, const uint8_t *buf) +{ + int au_headers_length, au_header_size, i; + GetBitContext getbitcontext; + RTPPayloadData *infos; + + infos = &rtsp_st->rtp_payload_data; + if (infos == NULL) + return -1; + + /* decode the first 2 bytes where the AUHeader sections are stored + length in bits */ + au_headers_length = AV_RB16(buf); + + if (au_headers_length > RTP_MAX_PACKET_LENGTH) + return -1; + + infos->au_headers_length_bytes = (au_headers_length + 7) / 8; + + /* skip AU headers length section (2 bytes) */ + buf += 2; + + init_get_bits(&getbitcontext, buf, infos->au_headers_length_bytes * 8); + + /* XXX: Wrong if optionnal additional sections are present (cts, dts etc...) */ + au_header_size = infos->sizelength + infos->indexlength; + if (au_header_size <= 0 || (au_headers_length % au_header_size != 0)) + return -1; + + infos->nb_au_headers = au_headers_length / au_header_size; + if (!infos->au_headers || infos->au_headers_allocated < infos->nb_au_headers) { + av_free(infos->au_headers); + infos->au_headers = av_malloc(sizeof(struct AUHeaders) * infos->nb_au_headers); + infos->au_headers_allocated = infos->nb_au_headers; + } + + /* XXX: We handle multiple AU Section as only one (need to fix this for interleaving) + In my test, the FAAD decoder does not behave correctly when sending each AU one by one + but does when sending the whole as one big packet... */ + infos->au_headers[0].size = 0; + infos->au_headers[0].index = 0; + for (i = 0; i < infos->nb_au_headers; ++i) { + infos->au_headers[0].size += get_bits_long(&getbitcontext, infos->sizelength); + infos->au_headers[0].index = get_bits_long(&getbitcontext, infos->indexlength); + } + + infos->nb_au_headers = 1; + + return 0; +} + + +/* Follows RFC 3640 */ +static int aac_parse_packet(AVFormatContext *ctx, + PayloadContext *data, + AVStream *st, + AVPacket *pkt, + uint32_t *timestamp, + const uint8_t *buf, int len, int flags) +{ + RTSPStream *rtsp_st = st->priv_data; + RTPPayloadData *infos; + + if (rtp_parse_mp4_au(rtsp_st, buf)) + return -1; + + infos = &rtsp_st->rtp_payload_data; + if (infos == NULL) + return -1; + buf += infos->au_headers_length_bytes + 2; + len -= infos->au_headers_length_bytes + 2; + + /* XXX: Fixme we only handle the case where rtp_parse_mp4_au define + one au_header */ + av_new_packet(pkt, infos->au_headers[0].size); + memcpy(pkt->data, buf, infos->au_headers[0].size); + + pkt->stream_index = st->index; + return 0; +} + static int parse_sdp_line(AVFormatContext *s, int st_index, PayloadContext *data, const char *line) { @@ -167,5 +249,5 @@ RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler = { .parse_sdp_a_line = parse_sdp_line, .open = NULL, .close = NULL, - .parse_packet = NULL + .parse_packet = aac_parse_packet }; -- cgit v1.2.3