* commit 'c6f1dc8e4cd967ae056698eafb891a08003c211c': rtpdec: Move setting the parsing flags to the actual depacketizers rtpdec: Split handling of mpeg12 audio/video to a separate depacketizer Conflicts: libavformat/rtpdec.c Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n1.2
| @@ -37,6 +37,7 @@ OBJS-$(CONFIG_RTPDEC) += rdt.o \ | |||||
| rtpdec_ilbc.o \ | rtpdec_ilbc.o \ | ||||
| rtpdec_jpeg.o \ | rtpdec_jpeg.o \ | ||||
| rtpdec_latm.o \ | rtpdec_latm.o \ | ||||
| rtpdec_mpeg12.o \ | |||||
| rtpdec_mpeg4.o \ | rtpdec_mpeg4.o \ | ||||
| rtpdec_mpegts.o \ | rtpdec_mpegts.o \ | ||||
| rtpdec_qcelp.o \ | rtpdec_qcelp.o \ | ||||
| @@ -74,6 +74,8 @@ void av_register_rtp_dynamic_payload_handlers(void) | |||||
| ff_register_dynamic_payload_handler(&ff_jpeg_dynamic_handler); | ff_register_dynamic_payload_handler(&ff_jpeg_dynamic_handler); | ||||
| ff_register_dynamic_payload_handler(&ff_mp4a_latm_dynamic_handler); | ff_register_dynamic_payload_handler(&ff_mp4a_latm_dynamic_handler); | ||||
| ff_register_dynamic_payload_handler(&ff_mp4v_es_dynamic_handler); | ff_register_dynamic_payload_handler(&ff_mp4v_es_dynamic_handler); | ||||
| ff_register_dynamic_payload_handler(&ff_mpeg_audio_dynamic_handler); | |||||
| ff_register_dynamic_payload_handler(&ff_mpeg_video_dynamic_handler); | |||||
| ff_register_dynamic_payload_handler(&ff_mpeg4_generic_dynamic_handler); | ff_register_dynamic_payload_handler(&ff_mpeg4_generic_dynamic_handler); | ||||
| ff_register_dynamic_payload_handler(&ff_mpegts_dynamic_handler); | ff_register_dynamic_payload_handler(&ff_mpegts_dynamic_handler); | ||||
| ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfv_handler); | ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfv_handler); | ||||
| @@ -500,18 +502,6 @@ RTPDemuxContext *ff_rtp_parse_open(AVFormatContext *s1, AVStream *st, | |||||
| rtp_init_statistics(&s->statistics, 0); | rtp_init_statistics(&s->statistics, 0); | ||||
| if (st) { | if (st) { | ||||
| switch (st->codec->codec_id) { | switch (st->codec->codec_id) { | ||||
| case AV_CODEC_ID_MPEG1VIDEO: | |||||
| case AV_CODEC_ID_MPEG2VIDEO: | |||||
| case AV_CODEC_ID_MP2: | |||||
| case AV_CODEC_ID_MP3: | |||||
| case AV_CODEC_ID_MPEG4: | |||||
| case AV_CODEC_ID_H263: | |||||
| case AV_CODEC_ID_H264: | |||||
| st->need_parsing = AVSTREAM_PARSE_FULL; | |||||
| break; | |||||
| case AV_CODEC_ID_VORBIS: | |||||
| st->need_parsing = AVSTREAM_PARSE_HEADERS; | |||||
| break; | |||||
| case AV_CODEC_ID_ADPCM_G722: | case AV_CODEC_ID_ADPCM_G722: | ||||
| /* According to RFC 3551, the stream clock rate is 8000 | /* According to RFC 3551, the stream clock rate is 8000 | ||||
| * even if the sample rate is 16000. */ | * even if the sample rate is 16000. */ | ||||
| @@ -583,12 +573,13 @@ static void finalize_packet(RTPDemuxContext *s, AVPacket *pkt, uint32_t timestam | |||||
| static int rtp_parse_packet_internal(RTPDemuxContext *s, AVPacket *pkt, | static int rtp_parse_packet_internal(RTPDemuxContext *s, AVPacket *pkt, | ||||
| const uint8_t *buf, int len) | const uint8_t *buf, int len) | ||||
| { | { | ||||
| unsigned int ssrc, h; | |||||
| unsigned int ssrc; | |||||
| int payload_type, seq, flags = 0; | int payload_type, seq, flags = 0; | ||||
| int ext; | int ext; | ||||
| AVStream *st; | AVStream *st; | ||||
| uint32_t timestamp; | uint32_t timestamp; | ||||
| int rv = 0; | int rv = 0; | ||||
| int h; | |||||
| ext = buf[0] & 0x10; | ext = buf[0] & 0x10; | ||||
| payload_type = buf[1] & 0x7f; | payload_type = buf[1] & 0x7f; | ||||
| @@ -649,45 +640,9 @@ static int rtp_parse_packet_internal(RTPDemuxContext *s, AVPacket *pkt, | |||||
| } else if (st) { | } else if (st) { | ||||
| /* At this point, the RTP header has been stripped; | /* At this point, the RTP header has been stripped; | ||||
| * This is ASSUMING that there is only 1 CSRC, which isn't wise. */ | * This is ASSUMING that there is only 1 CSRC, which isn't wise. */ | ||||
| switch (st->codec->codec_id) { | |||||
| case AV_CODEC_ID_MP2: | |||||
| case AV_CODEC_ID_MP3: | |||||
| /* better than nothing: skip MPEG audio RTP header */ | |||||
| if (len <= 4) | |||||
| return -1; | |||||
| h = AV_RB32(buf); | |||||
| len -= 4; | |||||
| buf += 4; | |||||
| if (av_new_packet(pkt, len) < 0) | |||||
| return AVERROR(ENOMEM); | |||||
| memcpy(pkt->data, buf, len); | |||||
| break; | |||||
| case AV_CODEC_ID_MPEG1VIDEO: | |||||
| case AV_CODEC_ID_MPEG2VIDEO: | |||||
| /* better than nothing: skip MPEG video RTP header */ | |||||
| if (len <= 4) | |||||
| return -1; | |||||
| h = AV_RB32(buf); | |||||
| buf += 4; | |||||
| len -= 4; | |||||
| if (h & (1 << 26)) { | |||||
| /* MPEG-2 */ | |||||
| if (len <= 4) | |||||
| return -1; | |||||
| buf += 4; | |||||
| len -= 4; | |||||
| } | |||||
| if (av_new_packet(pkt, len) < 0) | |||||
| return AVERROR(ENOMEM); | |||||
| memcpy(pkt->data, buf, len); | |||||
| break; | |||||
| default: | |||||
| if (av_new_packet(pkt, len) < 0) | |||||
| return AVERROR(ENOMEM); | |||||
| memcpy(pkt->data, buf, len); | |||||
| break; | |||||
| } | |||||
| if (av_new_packet(pkt, len) < 0) | |||||
| return AVERROR(ENOMEM); | |||||
| memcpy(pkt->data, buf, len); | |||||
| pkt->stream_index = st->index; | pkt->stream_index = st->index; | ||||
| } else { | } else { | ||||
| return AVERROR(EINVAL); | return AVERROR(EINVAL); | ||||
| @@ -49,6 +49,8 @@ extern RTPDynamicProtocolHandler ff_ilbc_dynamic_handler; | |||||
| extern RTPDynamicProtocolHandler ff_jpeg_dynamic_handler; | extern RTPDynamicProtocolHandler ff_jpeg_dynamic_handler; | ||||
| extern RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler; | extern RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler; | ||||
| extern RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler; | extern RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler; | ||||
| extern RTPDynamicProtocolHandler ff_mpeg_audio_dynamic_handler; | |||||
| extern RTPDynamicProtocolHandler ff_mpeg_video_dynamic_handler; | |||||
| extern RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler; | extern RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler; | ||||
| extern RTPDynamicProtocolHandler ff_mpegts_dynamic_handler; | extern RTPDynamicProtocolHandler ff_mpegts_dynamic_handler; | ||||
| extern RTPDynamicProtocolHandler ff_ms_rtp_asf_pfa_handler; | extern RTPDynamicProtocolHandler ff_ms_rtp_asf_pfa_handler; | ||||
| @@ -23,6 +23,14 @@ | |||||
| #include "rtpdec_formats.h" | #include "rtpdec_formats.h" | ||||
| #include "libavutil/intreadwrite.h" | #include "libavutil/intreadwrite.h" | ||||
| static int h263_init(AVFormatContext *ctx, int st_index, PayloadContext *data) | |||||
| { | |||||
| if (st_index < 0) | |||||
| return 0; | |||||
| ctx->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL; | |||||
| return 0; | |||||
| } | |||||
| int ff_h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, | int ff_h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, | ||||
| AVStream *st, AVPacket *pkt, uint32_t *timestamp, | AVStream *st, AVPacket *pkt, uint32_t *timestamp, | ||||
| const uint8_t *buf, int len, uint16_t seq, int flags) | const uint8_t *buf, int len, uint16_t seq, int flags) | ||||
| @@ -92,6 +100,7 @@ RTPDynamicProtocolHandler ff_h263_1998_dynamic_handler = { | |||||
| .enc_name = "H263-1998", | .enc_name = "H263-1998", | ||||
| .codec_type = AVMEDIA_TYPE_VIDEO, | .codec_type = AVMEDIA_TYPE_VIDEO, | ||||
| .codec_id = AV_CODEC_ID_H263, | .codec_id = AV_CODEC_ID_H263, | ||||
| .init = h263_init, | |||||
| .parse_packet = ff_h263_handle_packet, | .parse_packet = ff_h263_handle_packet, | ||||
| }; | }; | ||||
| @@ -99,5 +108,6 @@ RTPDynamicProtocolHandler ff_h263_2000_dynamic_handler = { | |||||
| .enc_name = "H263-2000", | .enc_name = "H263-2000", | ||||
| .codec_type = AVMEDIA_TYPE_VIDEO, | .codec_type = AVMEDIA_TYPE_VIDEO, | ||||
| .codec_id = AV_CODEC_ID_H263, | .codec_id = AV_CODEC_ID_H263, | ||||
| .init = h263_init, | |||||
| .parse_packet = ff_h263_handle_packet, | .parse_packet = ff_h263_handle_packet, | ||||
| }; | }; | ||||
| @@ -55,6 +55,14 @@ static void h263_free_context(PayloadContext *data) | |||||
| av_free(data); | av_free(data); | ||||
| } | } | ||||
| static int h263_init(AVFormatContext *ctx, int st_index, PayloadContext *data) | |||||
| { | |||||
| if (st_index < 0) | |||||
| return 0; | |||||
| ctx->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL; | |||||
| return 0; | |||||
| } | |||||
| static int h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, | static int h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, | ||||
| AVStream *st, AVPacket *pkt, uint32_t *timestamp, | AVStream *st, AVPacket *pkt, uint32_t *timestamp, | ||||
| const uint8_t *buf, int len, uint16_t seq, | const uint8_t *buf, int len, uint16_t seq, | ||||
| @@ -198,6 +206,7 @@ static int h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, | |||||
| RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler = { | RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler = { | ||||
| .codec_type = AVMEDIA_TYPE_VIDEO, | .codec_type = AVMEDIA_TYPE_VIDEO, | ||||
| .codec_id = AV_CODEC_ID_H263, | .codec_id = AV_CODEC_ID_H263, | ||||
| .init = h263_init, | |||||
| .parse_packet = h263_handle_packet, | .parse_packet = h263_handle_packet, | ||||
| .alloc = h263_new_context, | .alloc = h263_new_context, | ||||
| .free = h263_free_context, | .free = h263_free_context, | ||||
| @@ -338,6 +338,14 @@ static void h264_free_context(PayloadContext *data) | |||||
| av_free(data); | av_free(data); | ||||
| } | } | ||||
| static int h264_init(AVFormatContext *s, int st_index, PayloadContext *data) | |||||
| { | |||||
| if (st_index < 0) | |||||
| return 0; | |||||
| s->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL; | |||||
| return 0; | |||||
| } | |||||
| static int parse_h264_sdp_line(AVFormatContext *s, int st_index, | static int parse_h264_sdp_line(AVFormatContext *s, int st_index, | ||||
| PayloadContext *h264_data, const char *line) | PayloadContext *h264_data, const char *line) | ||||
| { | { | ||||
| @@ -383,6 +391,7 @@ RTPDynamicProtocolHandler ff_h264_dynamic_handler = { | |||||
| .enc_name = "H264", | .enc_name = "H264", | ||||
| .codec_type = AVMEDIA_TYPE_VIDEO, | .codec_type = AVMEDIA_TYPE_VIDEO, | ||||
| .codec_id = AV_CODEC_ID_H264, | .codec_id = AV_CODEC_ID_H264, | ||||
| .init = h264_init, | |||||
| .parse_sdp_a_line = parse_h264_sdp_line, | .parse_sdp_a_line = parse_h264_sdp_line, | ||||
| .alloc = h264_new_context, | .alloc = h264_new_context, | ||||
| .free = h264_free_context, | .free = h264_free_context, | ||||
| @@ -0,0 +1,72 @@ | |||||
| /* | |||||
| * Common code for the RTP depacketization of MPEG-1/2 formats. | |||||
| * Copyright (c) 2002 Fabrice Bellard | |||||
| * | |||||
| * This file is part of FFmpeg. | |||||
| * | |||||
| * FFmpeg is free software; you can redistribute it and/or | |||||
| * modify it under the terms of the GNU Lesser General Public | |||||
| * License as published by the Free Software Foundation; either | |||||
| * version 2.1 of the License, or (at your option) any later version. | |||||
| * | |||||
| * FFmpeg is distributed in the hope that it will be useful, | |||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||||
| * Lesser General Public License for more details. | |||||
| * | |||||
| * You should have received a copy of the GNU Lesser General Public | |||||
| * License along with FFmpeg; if not, write to the Free Software | |||||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||||
| */ | |||||
| #include "rtpdec_formats.h" | |||||
| #include "libavutil/intreadwrite.h" | |||||
| static int mpeg_init(AVFormatContext *ctx, int st_index, PayloadContext *data) | |||||
| { | |||||
| if (st_index < 0) | |||||
| return 0; | |||||
| ctx->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL; | |||||
| return 0; | |||||
| } | |||||
| static int mpeg_parse_packet(AVFormatContext *ctx, PayloadContext *data, | |||||
| AVStream *st, AVPacket *pkt, uint32_t *timestamp, | |||||
| const uint8_t *buf, int len, uint16_t seq, | |||||
| int flags) | |||||
| { | |||||
| unsigned int h; | |||||
| if (len <= 4) | |||||
| return AVERROR_INVALIDDATA; | |||||
| h = AV_RB32(buf); | |||||
| buf += 4; | |||||
| len -= 4; | |||||
| if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && h & (1 << 26)) { | |||||
| /* MPEG-2 */ | |||||
| if (len <= 4) | |||||
| return AVERROR_INVALIDDATA; | |||||
| buf += 4; | |||||
| len -= 4; | |||||
| } | |||||
| if (av_new_packet(pkt, len) < 0) | |||||
| return AVERROR(ENOMEM); | |||||
| memcpy(pkt->data, buf, len); | |||||
| pkt->stream_index = st->index; | |||||
| return 0; | |||||
| } | |||||
| RTPDynamicProtocolHandler ff_mpeg_audio_dynamic_handler = { | |||||
| .codec_type = AVMEDIA_TYPE_AUDIO, | |||||
| .codec_id = AV_CODEC_ID_MP3, | |||||
| .init = mpeg_init, | |||||
| .parse_packet = mpeg_parse_packet, | |||||
| .static_payload_id = 14, | |||||
| }; | |||||
| RTPDynamicProtocolHandler ff_mpeg_video_dynamic_handler = { | |||||
| .codec_type = AVMEDIA_TYPE_VIDEO, | |||||
| .codec_id = AV_CODEC_ID_MPEG2VIDEO, | |||||
| .init = mpeg_init, | |||||
| .parse_packet = mpeg_parse_packet, | |||||
| .static_payload_id = 32, | |||||
| }; | |||||
| @@ -252,10 +252,19 @@ static int parse_sdp_line(AVFormatContext *s, int st_index, | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| static int init_video(AVFormatContext *s, int st_index, PayloadContext *data) | |||||
| { | |||||
| if (st_index < 0) | |||||
| return 0; | |||||
| s->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL; | |||||
| return 0; | |||||
| } | |||||
| RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler = { | RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler = { | ||||
| .enc_name = "MP4V-ES", | .enc_name = "MP4V-ES", | ||||
| .codec_type = AVMEDIA_TYPE_VIDEO, | .codec_type = AVMEDIA_TYPE_VIDEO, | ||||
| .codec_id = AV_CODEC_ID_MPEG4, | .codec_id = AV_CODEC_ID_MPEG4, | ||||
| .init = init_video, | |||||
| .parse_sdp_a_line = parse_sdp_line, | .parse_sdp_a_line = parse_sdp_line, | ||||
| }; | }; | ||||
| @@ -69,6 +69,16 @@ static void xiph_free_context(PayloadContext * data) | |||||
| av_free(data); | av_free(data); | ||||
| } | } | ||||
| static int xiph_vorbis_init(AVFormatContext *ctx, int st_index, | |||||
| PayloadContext *data) | |||||
| { | |||||
| if (st_index < 0) | |||||
| return 0; | |||||
| ctx->streams[st_index]->need_parsing = AVSTREAM_PARSE_HEADERS; | |||||
| return 0; | |||||
| } | |||||
| static int xiph_handle_packet(AVFormatContext *ctx, PayloadContext *data, | static int xiph_handle_packet(AVFormatContext *ctx, PayloadContext *data, | ||||
| AVStream *st, AVPacket *pkt, uint32_t *timestamp, | AVStream *st, AVPacket *pkt, uint32_t *timestamp, | ||||
| const uint8_t *buf, int len, uint16_t seq, | const uint8_t *buf, int len, uint16_t seq, | ||||
| @@ -391,6 +401,7 @@ RTPDynamicProtocolHandler ff_vorbis_dynamic_handler = { | |||||
| .enc_name = "vorbis", | .enc_name = "vorbis", | ||||
| .codec_type = AVMEDIA_TYPE_AUDIO, | .codec_type = AVMEDIA_TYPE_AUDIO, | ||||
| .codec_id = AV_CODEC_ID_VORBIS, | .codec_id = AV_CODEC_ID_VORBIS, | ||||
| .init = xiph_vorbis_init, | |||||
| .parse_sdp_a_line = xiph_parse_sdp_line, | .parse_sdp_a_line = xiph_parse_sdp_line, | ||||
| .alloc = xiph_new_context, | .alloc = xiph_new_context, | ||||
| .free = xiph_free_context, | .free = xiph_free_context, | ||||