Revision ff13ba92

View differences:

libavformat/allformats.c
20 20
 */
21 21
#include "avformat.h"
22 22
#include "rtp_internal.h"
23
#include "rdt.h"
23 24

  
24 25
#define REGISTER_MUXER(X,x) { \
25 26
          extern AVOutputFormat x##_muxer; \
......
165 166
    REGISTER_DEMUXER  (SDP, sdp);
166 167
#ifdef CONFIG_SDP_DEMUXER
167 168
    av_register_rtp_dynamic_payload_handlers();
169
    av_register_rdt_dynamic_payload_handlers();
168 170
#endif
169 171
    REGISTER_DEMUXER  (SEGAFILM, segafilm);
170 172
    REGISTER_DEMUXER  (SHORTEN, shorten);
libavformat/rdt.c
27 27

  
28 28
#include "avformat.h"
29 29
#include "libavutil/avstring.h"
30
#include "rtp_internal.h"
30 31
#include "rdt.h"
31 32
#include "libavutil/base64.h"
32 33
#include "libavutil/md5.h"
33 34
#include "rm.h"
34 35
#include "internal.h"
35 36

  
37
typedef struct rdt_data {
38
    AVFormatContext *rmctx;
39
    uint8_t *mlti_data;
40
    unsigned int mlti_data_size;
41
} rdt_data;
42

  
36 43
void
37 44
ff_rdt_calc_response_and_checksum(char response[41], char chksum[9],
38 45
                                  const char *challenge)
......
71 78
        chksum[i] = response[i * 4];
72 79
    chksum[8] = 0;
73 80
}
81

  
82
static int
83
rdt_load_mdpr (rdt_data *rdt, AVStream *st, int rule_nr)
84
{
85
    ByteIOContext *pb;
86
    int size;
87
    uint32_t tag;
88

  
89
    /**
90
     * Layout of the MLTI chunk:
91
     * 4:MLTI
92
     * 2:<number of streams>
93
     * Then for each stream ([number_of_streams] times):
94
     *     2:<mdpr index>
95
     * 2:<number of mdpr chunks>
96
     * Then for each mdpr chunk ([number_of_mdpr_chunks] times):
97
     *     4:<size>
98
     *     [size]:<data>
99
     * we skip MDPR chunks until we reach the one of the stream
100
     * we're interested in, and forward that ([size]+[data]) to
101
     * the RM demuxer to parse the stream-specific header data.
102
     */
103
    if (!rdt->mlti_data)
104
        return -1;
105
    url_open_buf(&pb, rdt->mlti_data, rdt->mlti_data_size, URL_RDONLY);
106
    tag = get_le32(pb);
107
    if (tag == MKTAG('M', 'L', 'T', 'I')) {
108
        int num, chunk_nr;
109

  
110
        /* read index of MDPR chunk numbers */
111
        num = get_be16(pb);
112
        if (rule_nr < 0 || rule_nr >= num)
113
            return -1;
114
        url_fskip(pb, rule_nr * 2);
115
        chunk_nr = get_be16(pb);
116
        url_fskip(pb, (num - 1 - rule_nr) * 2);
117

  
118
        /* read MDPR chunks */
119
        num = get_be16(pb);
120
        if (chunk_nr >= num)
121
            return -1;
122
        while (chunk_nr--)
123
            url_fskip(pb, get_be32(pb));
124
        size = get_be32(pb);
125
    } else {
126
        size = rdt->mlti_data_size;
127
        url_fseek(pb, 0, SEEK_SET);
128
    }
129
    rdt->rmctx->pb = pb;
130
    if (ff_rm_read_mdpr_codecdata(rdt->rmctx, st, size) < 0)
131
        return -1;
132

  
133
    url_close_buf(pb);
134
    return 0;
135
}
136

  
137
static unsigned char *
138
rdt_parse_b64buf (unsigned int *target_len, const char *p)
139
{
140
    unsigned char *target;
141
    int len = strlen(p);
142
    if (*p == '\"') {
143
        p++;
144
        len -= 2; /* skip embracing " at start/end */
145
    }
146
    *target_len = len * 3 / 4;
147
    target = av_mallocz(*target_len + FF_INPUT_BUFFER_PADDING_SIZE);
148
    av_base64_decode(target, p, *target_len);
149
    return target;
150
}
151

  
152
static int
153
rdt_parse_sdp_line (AVStream *stream, void *d, const char *line)
154
{
155
    rdt_data *rdt = d;
156
    const char *p = line;
157

  
158
    if (av_strstart(p, "OpaqueData:buffer;", &p)) {
159
        rdt->mlti_data = rdt_parse_b64buf(&rdt->mlti_data_size, p);
160
        rdt_load_mdpr(rdt, stream, 0);
161
    } else if (av_strstart(p, "StartTime:integer;", &p))
162
        stream->first_dts = atoi(p);
163

  
164
    return 0;
165
}
166

  
167
static void *
168
rdt_new_extradata (void)
169
{
170
    rdt_data *rdt = av_mallocz(sizeof(rdt_data));
171

  
172
    av_open_input_stream(&rdt->rmctx, NULL, "", &rdt_demuxer, NULL);
173

  
174
    return rdt;
175
}
176

  
177
static void
178
rdt_free_extradata (void *d)
179
{
180
    rdt_data *rdt = d;
181

  
182
    if (rdt->rmctx)
183
        av_close_input_stream(rdt->rmctx);
184
    av_freep(&rdt->mlti_data);
185
    av_free(rdt);
186
}
187

  
188
#define RDT_HANDLER(n, s, t) \
189
static RTPDynamicProtocolHandler ff_rdt_ ## n ## _handler = { \
190
    s, \
191
    t, \
192
    CODEC_ID_NONE, \
193
    rdt_parse_sdp_line, \
194
    rdt_new_extradata, \
195
    rdt_free_extradata \
196
};
197

  
198
RDT_HANDLER(live_video, "x-pn-multirate-realvideo-live", CODEC_TYPE_VIDEO);
199
RDT_HANDLER(live_audio, "x-pn-multirate-realaudio-live", CODEC_TYPE_AUDIO);
200
RDT_HANDLER(video,      "x-pn-realvideo",                CODEC_TYPE_VIDEO);
201
RDT_HANDLER(audio,      "x-pn-realaudio",                CODEC_TYPE_AUDIO);
202

  
203
void av_register_rdt_dynamic_payload_handlers(void)
204
{
205
    ff_register_dynamic_payload_handler(&ff_rdt_video_handler);
206
    ff_register_dynamic_payload_handler(&ff_rdt_audio_handler);
207
    ff_register_dynamic_payload_handler(&ff_rdt_live_video_handler);
208
    ff_register_dynamic_payload_handler(&ff_rdt_live_audio_handler);
209
}
libavformat/rdt.h
37 37
void ff_rdt_calc_response_and_checksum(char response[41], char chksum[9],
38 38
                                       const char *challenge);
39 39

  
40
/**
41
 * Register RDT-related dynamic payload handlers with our cache.
42
 */
43
void av_register_rdt_dynamic_payload_handlers(void);
44

  
40 45
#endif /* AVFORMAT_RDT_H */
libavformat/rm.h
63 63
    int sub_packet_lengths[16]; /// Length of each aac subpacket
64 64
} RMContext;
65 65

  
66
/*< input format for Realmedia-style RTSP streams */
67
extern AVInputFormat rdt_demuxer;
68

  
66 69
/**
67 70
 * Read the MDPR chunk, which contains stream-specific codec initialization
68 71
 * parameters.
libavformat/rmdec.c
795 795
    NULL,
796 796
    rm_read_dts,
797 797
};
798

  
799
AVInputFormat rdt_demuxer = {
800
    "rdt",
801
    NULL_IF_CONFIG_SMALL("RDT demuxer"),
802
    sizeof(RMContext),
803
    NULL, NULL, NULL, rm_read_close, NULL, NULL
804
};

Also available in: Unified diff