00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00028 #include "avformat.h"
00029 #include "rtp.h"
00030 #include "rtpdec.h"
00031 #include "isom.h"
00032 #include "libavcodec/get_bits.h"
00033
00034 struct PayloadContext {
00035 AVPacket pkt;
00036 int bytes_per_frame, remaining;
00037 uint32_t timestamp;
00038 };
00039
00040 static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt,
00041 AVStream *st, AVPacket *pkt,
00042 uint32_t *timestamp, const uint8_t *buf,
00043 int len, int flags)
00044 {
00045 ByteIOContext pb;
00046 GetBitContext gb;
00047 int packing_scheme, has_payload_desc, has_packet_info, alen,
00048 has_marker_bit = flags & RTP_FLAG_MARKER;
00049
00050 if (qt->remaining) {
00051 int num = qt->pkt.size / qt->bytes_per_frame;
00052
00053 if (av_new_packet(pkt, qt->bytes_per_frame))
00054 return AVERROR(ENOMEM);
00055 pkt->stream_index = st->index;
00056 pkt->flags = qt->pkt.flags;
00057 memcpy(pkt->data,
00058 &qt->pkt.data[(num - qt->remaining) * qt->bytes_per_frame],
00059 qt->bytes_per_frame);
00060 if (--qt->remaining == 0) {
00061 av_freep(&qt->pkt.data);
00062 qt->pkt.size = 0;
00063 }
00064 return qt->remaining > 0;
00065 }
00066
00071 init_get_bits(&gb, buf, len << 3);
00072 init_put_byte(&pb, buf, len, 0, NULL, NULL, NULL, NULL);
00073
00074 if (len < 4)
00075 return AVERROR_INVALIDDATA;
00076
00077 skip_bits(&gb, 4);
00078 if ((packing_scheme = get_bits(&gb, 2)) == 0)
00079 return AVERROR_INVALIDDATA;
00080 if (get_bits1(&gb))
00081 flags |= RTP_FLAG_KEY;
00082 has_payload_desc = get_bits1(&gb);
00083 has_packet_info = get_bits1(&gb);
00084 skip_bits(&gb, 23);
00085
00086 if (has_payload_desc) {
00087 int data_len, pos, is_start, is_finish;
00088 uint32_t tag;
00089
00090 pos = get_bits_count(&gb) >> 3;
00091 if (pos + 12 > len)
00092 return AVERROR_INVALIDDATA;
00093
00094 skip_bits(&gb, 2);
00095 is_start = get_bits1(&gb);
00096 is_finish = get_bits1(&gb);
00097 if (!is_start || !is_finish) {
00098 av_log_missing_feature(s, "RTP-X-QT with payload description "
00099 "split over several packets", 1);
00100 return AVERROR_NOTSUPP;
00101 }
00102 skip_bits(&gb, 12);
00103 data_len = get_bits(&gb, 16);
00104
00105 url_fseek(&pb, pos + 4, SEEK_SET);
00106 tag = get_le32(&pb);
00107 if ((st->codec->codec_type == CODEC_TYPE_VIDEO &&
00108 tag != MKTAG('v','i','d','e')) ||
00109 (st->codec->codec_type == CODEC_TYPE_AUDIO &&
00110 tag != MKTAG('s','o','u','n')))
00111 return AVERROR_INVALIDDATA;
00112 av_set_pts_info(st, 32, 1, get_be32(&pb));
00113
00114 if (pos + data_len > len)
00115 return AVERROR_INVALIDDATA;
00116
00117 while (url_ftell(&pb) + 4 < pos + data_len) {
00118 int tlv_len = get_be16(&pb);
00119 tag = get_le16(&pb);
00120 if (url_ftell(&pb) + tlv_len > pos + data_len)
00121 return AVERROR_INVALIDDATA;
00122
00123 #define MKTAG16(a,b) MKTAG(a,b,0,0)
00124 switch (tag) {
00125 case MKTAG16('s','d'): {
00126 MOVStreamContext *msc;
00127 void *priv_data = st->priv_data;
00128 int nb_streams = s->nb_streams;
00129 MOVContext *mc = av_mallocz(sizeof(*mc));
00130 if (!mc)
00131 return AVERROR(ENOMEM);
00132 mc->fc = s;
00133 st->priv_data = msc = av_mallocz(sizeof(MOVStreamContext));
00134 if (!msc) {
00135 av_free(mc);
00136 st->priv_data = priv_data;
00137 return AVERROR(ENOMEM);
00138 }
00139
00140
00141 s->nb_streams = st->index + 1;
00142 ff_mov_read_stsd_entries(mc, &pb, 1);
00143 qt->bytes_per_frame = msc->bytes_per_frame;
00144 av_free(msc);
00145 av_free(mc);
00146 st->priv_data = priv_data;
00147 s->nb_streams = nb_streams;
00148 break;
00149 }
00150 default:
00151 url_fskip(&pb, tlv_len);
00152 break;
00153 }
00154 }
00155
00156
00157 url_fskip(&pb, ((url_ftell(&pb) + 3) & ~3) - url_ftell(&pb));
00158 } else
00159 url_fseek(&pb, 4, SEEK_SET);
00160
00161 if (has_packet_info) {
00162 av_log_missing_feature(s, "RTP-X-QT with packet specific info", 1);
00163 return AVERROR_NOTSUPP;
00164 }
00165
00166 alen = len - url_ftell(&pb);
00167 if (alen <= 0)
00168 return AVERROR_INVALIDDATA;
00169
00170 switch (packing_scheme) {
00171 case 3:
00172 if (qt->pkt.size > 0 && qt->timestamp == *timestamp) {
00173 qt->pkt.data = av_realloc(qt->pkt.data, qt->pkt.size + alen +
00174 FF_INPUT_BUFFER_PADDING_SIZE);
00175 } else {
00176 av_freep(&qt->pkt.data);
00177 av_init_packet(&qt->pkt);
00178 qt->pkt.data = av_malloc(alen + FF_INPUT_BUFFER_PADDING_SIZE);
00179 qt->pkt.size = 0;
00180 qt->timestamp = *timestamp;
00181 }
00182 if (!qt->pkt.data)
00183 return AVERROR(ENOMEM);
00184 memcpy(qt->pkt.data + qt->pkt.size, buf + url_ftell(&pb), alen);
00185 qt->pkt.size += alen;
00186 if (has_marker_bit) {
00187 *pkt = qt->pkt;
00188 qt->pkt.size = 0;
00189 qt->pkt.data = NULL;
00190 pkt->flags = flags & RTP_FLAG_KEY ? AV_PKT_FLAG_KEY : 0;
00191 pkt->stream_index = st->index;
00192 pkt->destruct = av_destruct_packet;
00193 memset(pkt->data + pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
00194 return 0;
00195 }
00196 return AVERROR(EAGAIN);
00197
00198 case 1:
00199 if (qt->bytes_per_frame == 0 ||
00200 alen % qt->bytes_per_frame != 0)
00201 return AVERROR_INVALIDDATA;
00202 qt->remaining = (alen / qt->bytes_per_frame) - 1;
00203 if (av_new_packet(pkt, qt->bytes_per_frame))
00204 return AVERROR(ENOMEM);
00205 memcpy(pkt->data, buf + url_ftell(&pb), qt->bytes_per_frame);
00206 pkt->flags = flags & RTP_FLAG_KEY ? AV_PKT_FLAG_KEY : 0;
00207 pkt->stream_index = st->index;
00208 if (qt->remaining > 0) {
00209 av_freep(&qt->pkt.data);
00210 qt->pkt.data = av_malloc(qt->remaining * qt->bytes_per_frame);
00211 if (!qt->pkt.data) {
00212 av_free_packet(pkt);
00213 return AVERROR(ENOMEM);
00214 }
00215 qt->pkt.size = qt->remaining * qt->bytes_per_frame;
00216 memcpy(qt->pkt.data,
00217 buf + url_ftell(&pb) + qt->bytes_per_frame,
00218 qt->remaining * qt->bytes_per_frame);
00219 qt->pkt.flags = pkt->flags;
00220 return 1;
00221 }
00222 return 0;
00223
00224 default:
00225 av_log_missing_feature(NULL, "RTP-X-QT with packing scheme 2", 1);
00226 return AVERROR_NOTSUPP;
00227 }
00228 }
00229
00230 static PayloadContext *qt_rtp_new(void)
00231 {
00232 return av_mallocz(sizeof(PayloadContext));
00233 }
00234
00235 static void qt_rtp_free(PayloadContext *qt)
00236 {
00237 av_freep(&qt->pkt.data);
00238 av_free(qt);
00239 }
00240
00241 #define RTP_QT_HANDLER(m, n, s, t) \
00242 RTPDynamicProtocolHandler ff_ ## m ## _rtp_ ## n ## _handler = { \
00243 .enc_name = s, \
00244 .codec_type = t, \
00245 .codec_id = CODEC_ID_NONE, \
00246 .open = qt_rtp_new, \
00247 .close = qt_rtp_free, \
00248 .parse_packet = qt_rtp_parse_packet, \
00249 };
00250
00251 RTP_QT_HANDLER(qt, vid, "X-QT", CODEC_TYPE_VIDEO);
00252 RTP_QT_HANDLER(qt, aud, "X-QT", CODEC_TYPE_AUDIO);
00253 RTP_QT_HANDLER(quicktime, vid, "X-QUICKTIME", CODEC_TYPE_VIDEO);
00254 RTP_QT_HANDLER(quicktime, aud, "X-QUICKTIME", CODEC_TYPE_AUDIO);