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