Patch by Josh Allmann, joshua dot allmann at gmail Originally committed as revision 23772 to svn://svn.ffmpeg.org/ffmpeg/trunktags/n0.8
| @@ -315,9 +315,8 @@ void rtp_send_punch_packets(URLContext* rtp_handle) | |||||
| * open a new RTP parse context for stream 'st'. 'st' can be NULL for | * open a new RTP parse context for stream 'st'. 'st' can be NULL for | ||||
| * MPEG2TS streams to indicate that they should be demuxed inside the | * MPEG2TS streams to indicate that they should be demuxed inside the | ||||
| * rtp demux (otherwise CODEC_ID_MPEG2TS packets are returned) | * rtp demux (otherwise CODEC_ID_MPEG2TS packets are returned) | ||||
| * TODO: change this to not take rtp_payload data, and use the new dynamic payload system. | |||||
| */ | */ | ||||
| RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *rtpc, int payload_type, RTPPayloadData *rtp_payload_data) | |||||
| RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *rtpc, int payload_type) | |||||
| { | { | ||||
| RTPDemuxContext *s; | RTPDemuxContext *s; | ||||
| @@ -329,7 +328,6 @@ RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *r | |||||
| s->first_rtcp_ntp_time = AV_NOPTS_VALUE; | s->first_rtcp_ntp_time = AV_NOPTS_VALUE; | ||||
| s->ic = s1; | s->ic = s1; | ||||
| s->st = st; | s->st = st; | ||||
| s->rtp_payload_data = rtp_payload_data; | |||||
| rtp_init_statistics(&s->statistics, 0); // do we know the initial sequence from sdp? | rtp_init_statistics(&s->statistics, 0); // do we know the initial sequence from sdp? | ||||
| if (!strcmp(ff_rtp_enc_name(payload_type), "MP2T")) { | if (!strcmp(ff_rtp_enc_name(payload_type), "MP2T")) { | ||||
| s->ts = ff_mpegts_parse_open(s->ic); | s->ts = ff_mpegts_parse_open(s->ic); | ||||
| @@ -528,9 +526,6 @@ int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt, | |||||
| void rtp_parse_close(RTPDemuxContext *s) | void rtp_parse_close(RTPDemuxContext *s) | ||||
| { | { | ||||
| // TODO: fold this into the protocol specific data fields. | |||||
| av_free(s->rtp_payload_data->mode); | |||||
| av_free(s->rtp_payload_data->au_headers); | |||||
| if (!strcmp(ff_rtp_enc_name(s->payload_type), "MP2T")) { | if (!strcmp(ff_rtp_enc_name(s->payload_type), "MP2T")) { | ||||
| ff_mpegts_parse_close(s->ts); | ff_mpegts_parse_close(s->ts); | ||||
| } | } | ||||
| @@ -26,34 +26,6 @@ | |||||
| #include "avformat.h" | #include "avformat.h" | ||||
| #include "rtp.h" | #include "rtp.h" | ||||
| /** Structure listing useful vars to parse RTP packet payload*/ | |||||
| typedef struct rtp_payload_data | |||||
| { | |||||
| int sizelength; | |||||
| int indexlength; | |||||
| int indexdeltalength; | |||||
| int profile_level_id; | |||||
| int streamtype; | |||||
| int objecttype; | |||||
| char *mode; | |||||
| /** mpeg 4 AU headers */ | |||||
| struct AUHeaders { | |||||
| int size; | |||||
| int index; | |||||
| int cts_flag; | |||||
| int cts; | |||||
| int dts_flag; | |||||
| int dts; | |||||
| int rap_flag; | |||||
| int streamstate; | |||||
| } *au_headers; | |||||
| int au_headers_allocated; | |||||
| int nb_au_headers; | |||||
| int au_headers_length_bytes; | |||||
| int cur_au_index; | |||||
| } RTPPayloadData; | |||||
| typedef struct PayloadContext PayloadContext; | typedef struct PayloadContext PayloadContext; | ||||
| typedef struct RTPDynamicProtocolHandler_s RTPDynamicProtocolHandler; | typedef struct RTPDynamicProtocolHandler_s RTPDynamicProtocolHandler; | ||||
| @@ -61,7 +33,7 @@ typedef struct RTPDynamicProtocolHandler_s RTPDynamicProtocolHandler; | |||||
| #define RTP_MAX_PACKET_LENGTH 1500 /* XXX: suppress this define */ | #define RTP_MAX_PACKET_LENGTH 1500 /* XXX: suppress this define */ | ||||
| typedef struct RTPDemuxContext RTPDemuxContext; | typedef struct RTPDemuxContext RTPDemuxContext; | ||||
| RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *rtpc, int payload_type, RTPPayloadData *rtp_payload_data); | |||||
| RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *rtpc, int payload_type); | |||||
| void rtp_parse_set_dynamic_protocol(RTPDemuxContext *s, PayloadContext *ctx, | void rtp_parse_set_dynamic_protocol(RTPDemuxContext *s, PayloadContext *ctx, | ||||
| RTPDynamicProtocolHandler *handler); | RTPDynamicProtocolHandler *handler); | ||||
| int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt, | int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt, | ||||
| @@ -187,9 +159,6 @@ struct RTPDemuxContext { | |||||
| uint8_t buf[RTP_MAX_PACKET_LENGTH]; | uint8_t buf[RTP_MAX_PACKET_LENGTH]; | ||||
| uint8_t *buf_ptr; | uint8_t *buf_ptr; | ||||
| /* special infos for au headers parsing */ | |||||
| RTPPayloadData *rtp_payload_data; // TODO: Move into dynamic payload handlers | |||||
| /* dynamic payload stuff */ | /* dynamic payload stuff */ | ||||
| DynamicPayloadPacketHandlerProc parse_packet; ///< This is also copied from the dynamic protocol handler structure | DynamicPayloadPacketHandlerProc parse_packet; ///< This is also copied from the dynamic protocol handler structure | ||||
| PayloadContext *dynamic_protocol_context; ///< This is a copy from the values setup from the sdp parsing, in rtsp.c don't free me. | PayloadContext *dynamic_protocol_context; ///< This is a copy from the values setup from the sdp parsing, in rtsp.c don't free me. | ||||
| @@ -33,7 +33,33 @@ | |||||
| #include "libavcodec/get_bits.h" | #include "libavcodec/get_bits.h" | ||||
| #include <strings.h> | #include <strings.h> | ||||
| #include "rtsp.h" //XXX remove this dependency | |||||
| /** Structure listing useful vars to parse RTP packet payload*/ | |||||
| struct PayloadContext | |||||
| { | |||||
| int sizelength; | |||||
| int indexlength; | |||||
| int indexdeltalength; | |||||
| int profile_level_id; | |||||
| int streamtype; | |||||
| int objecttype; | |||||
| char *mode; | |||||
| /** mpeg 4 AU headers */ | |||||
| struct AUHeaders { | |||||
| int size; | |||||
| int index; | |||||
| int cts_flag; | |||||
| int cts; | |||||
| int dts_flag; | |||||
| int dts; | |||||
| int rap_flag; | |||||
| int streamstate; | |||||
| } *au_headers; | |||||
| int au_headers_allocated; | |||||
| int nb_au_headers; | |||||
| int au_headers_length_bytes; | |||||
| int cur_au_index; | |||||
| }; | |||||
| /* return the length and optionally the data */ | /* return the length and optionally the data */ | ||||
| static int hex_to_data(uint8_t *data, const char *p) | static int hex_to_data(uint8_t *data, const char *p) | ||||
| @@ -76,20 +102,40 @@ typedef struct { | |||||
| static const AttrNameMap attr_names[]= | static const AttrNameMap attr_names[]= | ||||
| { | { | ||||
| { "SizeLength", ATTR_NAME_TYPE_INT, | { "SizeLength", ATTR_NAME_TYPE_INT, | ||||
| offsetof(RTPPayloadData, sizelength) }, | |||||
| offsetof(PayloadContext, sizelength) }, | |||||
| { "IndexLength", ATTR_NAME_TYPE_INT, | { "IndexLength", ATTR_NAME_TYPE_INT, | ||||
| offsetof(RTPPayloadData, indexlength) }, | |||||
| offsetof(PayloadContext, indexlength) }, | |||||
| { "IndexDeltaLength", ATTR_NAME_TYPE_INT, | { "IndexDeltaLength", ATTR_NAME_TYPE_INT, | ||||
| offsetof(RTPPayloadData, indexdeltalength) }, | |||||
| offsetof(PayloadContext, indexdeltalength) }, | |||||
| { "profile-level-id", ATTR_NAME_TYPE_INT, | { "profile-level-id", ATTR_NAME_TYPE_INT, | ||||
| offsetof(RTPPayloadData, profile_level_id) }, | |||||
| offsetof(PayloadContext, profile_level_id) }, | |||||
| { "StreamType", ATTR_NAME_TYPE_INT, | { "StreamType", ATTR_NAME_TYPE_INT, | ||||
| offsetof(RTPPayloadData, streamtype) }, | |||||
| offsetof(PayloadContext, streamtype) }, | |||||
| { "mode", ATTR_NAME_TYPE_STR, | { "mode", ATTR_NAME_TYPE_STR, | ||||
| offsetof(RTPPayloadData, mode) }, | |||||
| offsetof(PayloadContext, mode) }, | |||||
| { NULL, -1, -1 }, | { NULL, -1, -1 }, | ||||
| }; | }; | ||||
| static PayloadContext *new_context(void) | |||||
| { | |||||
| return av_mallocz(sizeof(PayloadContext)); | |||||
| } | |||||
| static void free_context(PayloadContext * data) | |||||
| { | |||||
| int i; | |||||
| for (i = 0; i < data->nb_au_headers; i++) { | |||||
| /* according to rtp_parse_mp4_au, we treat multiple | |||||
| * au headers as one, so nb_au_headers is always 1. | |||||
| * loop anyway in case this changes. | |||||
| * (note: changes done carelessly might lead to a double free) | |||||
| */ | |||||
| av_free(&data->au_headers[i]); | |||||
| } | |||||
| av_free(data->mode); | |||||
| av_free(data); | |||||
| } | |||||
| static int parse_fmtp_config(AVCodecContext * codec, char *value) | static int parse_fmtp_config(AVCodecContext * codec, char *value) | ||||
| { | { | ||||
| /* decode the hexa encoded parameter */ | /* decode the hexa encoded parameter */ | ||||
| @@ -104,15 +150,10 @@ static int parse_fmtp_config(AVCodecContext * codec, char *value) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| static int rtp_parse_mp4_au(RTSPStream *rtsp_st, const uint8_t *buf) | |||||
| static int rtp_parse_mp4_au(PayloadContext *infos, const uint8_t *buf) | |||||
| { | { | ||||
| int au_headers_length, au_header_size, i; | int au_headers_length, au_header_size, i; | ||||
| GetBitContext getbitcontext; | 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 | /* decode the first 2 bytes where the AUHeader sections are stored | ||||
| length in bits */ | length in bits */ | ||||
| @@ -158,21 +199,15 @@ static int rtp_parse_mp4_au(RTSPStream *rtsp_st, const uint8_t *buf) | |||||
| /* Follows RFC 3640 */ | /* Follows RFC 3640 */ | ||||
| static int aac_parse_packet(AVFormatContext *ctx, | static int aac_parse_packet(AVFormatContext *ctx, | ||||
| PayloadContext *data, | |||||
| PayloadContext *infos, | |||||
| AVStream *st, | AVStream *st, | ||||
| AVPacket *pkt, | AVPacket *pkt, | ||||
| uint32_t *timestamp, | uint32_t *timestamp, | ||||
| const uint8_t *buf, int len, int flags) | const uint8_t *buf, int len, int flags) | ||||
| { | { | ||||
| RTSPStream *rtsp_st = st->priv_data; | |||||
| RTPPayloadData *infos; | |||||
| if (rtp_parse_mp4_au(rtsp_st, buf)) | |||||
| if (rtp_parse_mp4_au(infos, buf)) | |||||
| return -1; | return -1; | ||||
| infos = &rtsp_st->rtp_payload_data; | |||||
| if (infos == NULL) | |||||
| return -1; | |||||
| buf += infos->au_headers_length_bytes + 2; | buf += infos->au_headers_length_bytes + 2; | ||||
| len -= infos->au_headers_length_bytes + 2; | len -= infos->au_headers_length_bytes + 2; | ||||
| @@ -186,15 +221,13 @@ static int aac_parse_packet(AVFormatContext *ctx, | |||||
| } | } | ||||
| static int parse_sdp_line(AVFormatContext *s, int st_index, | static int parse_sdp_line(AVFormatContext *s, int st_index, | ||||
| PayloadContext *data, const char *line) | |||||
| PayloadContext *rtp_payload_data, const char *line) | |||||
| { | { | ||||
| const char *p; | const char *p; | ||||
| char value[4096], attr[25]; | char value[4096], attr[25]; | ||||
| int res = 0, i; | int res = 0, i; | ||||
| AVStream *st = s->streams[st_index]; | AVStream *st = s->streams[st_index]; | ||||
| RTSPStream *rtsp_st = st->priv_data; | |||||
| AVCodecContext* codec = st->codec; | AVCodecContext* codec = st->codec; | ||||
| RTPPayloadData *rtp_payload_data = &rtsp_st->rtp_payload_data; | |||||
| if (av_strstart(line, "fmtp:", &p)) { | if (av_strstart(line, "fmtp:", &p)) { | ||||
| // remove protocol identifier | // remove protocol identifier | ||||
| @@ -247,7 +280,7 @@ RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler = { | |||||
| .codec_type = AVMEDIA_TYPE_AUDIO, | .codec_type = AVMEDIA_TYPE_AUDIO, | ||||
| .codec_id = CODEC_ID_AAC, | .codec_id = CODEC_ID_AAC, | ||||
| .parse_sdp_a_line = parse_sdp_line, | .parse_sdp_a_line = parse_sdp_line, | ||||
| .open = NULL, | |||||
| .close = NULL, | |||||
| .open = new_context, | |||||
| .close = free_context, | |||||
| .parse_packet = aac_parse_packet | .parse_packet = aac_parse_packet | ||||
| }; | }; | ||||
| @@ -561,8 +561,7 @@ static int rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st) | |||||
| rtsp_st->dynamic_handler); | rtsp_st->dynamic_handler); | ||||
| else | else | ||||
| rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle, | rtsp_st->transport_priv = rtp_parse_open(s, st, rtsp_st->rtp_handle, | ||||
| rtsp_st->sdp_payload_type, | |||||
| &rtsp_st->rtp_payload_data); | |||||
| rtsp_st->sdp_payload_type); | |||||
| if (!rtsp_st->transport_priv) { | if (!rtsp_st->transport_priv) { | ||||
| return AVERROR(ENOMEM); | return AVERROR(ENOMEM); | ||||
| @@ -323,11 +323,6 @@ typedef struct RTSPStream { | |||||
| int sdp_payload_type; /**< payload type */ | int sdp_payload_type; /**< payload type */ | ||||
| //@} | //@} | ||||
| /** rtp payload parsing infos from SDP (i.e. mapping between private | |||||
| * payload IDs and media-types (string), so that we can derive what | |||||
| * type of payload we're dealing with (and how to parse it). */ | |||||
| RTPPayloadData rtp_payload_data; | |||||
| /** The following are used for dynamic protocols (rtp_*.c/rdt.c) */ | /** The following are used for dynamic protocols (rtp_*.c/rdt.c) */ | ||||
| //@{ | //@{ | ||||
| /** handler structure */ | /** handler structure */ | ||||