00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00030 #include "libavcodec/bytestream.h"
00031
00032 #include "rtpdec_formats.h"
00033
00034 struct PayloadContext {
00035 AVIOContext *data;
00036 uint32_t timestamp;
00037 };
00038
00039 static int vp8_handle_packet(AVFormatContext *ctx,
00040 PayloadContext *vp8,
00041 AVStream *st,
00042 AVPacket *pkt,
00043 uint32_t *timestamp,
00044 const uint8_t *buf,
00045 int len, int flags)
00046 {
00047 int start_partition, end_packet;
00048 int extended_bits, part_id;
00049 int pictureid_present = 0, tl0picidx_present = 0, tid_present = 0,
00050 keyidx_present = 0;
00051
00052 if (len < 1)
00053 return AVERROR_INVALIDDATA;
00054
00055 extended_bits = buf[0] & 0x80;
00056 start_partition = buf[0] & 0x10;
00057 part_id = buf[0] & 0x0f;
00058 end_packet = flags & RTP_FLAG_MARKER;
00059 buf++;
00060 len--;
00061 if (extended_bits) {
00062 if (len < 1)
00063 return AVERROR_INVALIDDATA;
00064 pictureid_present = buf[0] & 0x80;
00065 tl0picidx_present = buf[0] & 0x40;
00066 tid_present = buf[0] & 0x20;
00067 keyidx_present = buf[0] & 0x10;
00068 buf++;
00069 len--;
00070 }
00071 if (pictureid_present) {
00072 int size;
00073 if (len < 1)
00074 return AVERROR_INVALIDDATA;
00075 size = buf[0] & 0x80 ? 2 : 1;
00076 buf += size;
00077 len -= size;
00078 }
00079 if (tl0picidx_present) {
00080
00081 buf++;
00082 len--;
00083 }
00084 if (tid_present || keyidx_present) {
00085
00086 buf++;
00087 len--;
00088 }
00089 if (len < 1)
00090 return AVERROR_INVALIDDATA;
00091
00092 if (start_partition && part_id == 0) {
00093 int res;
00094 if (vp8->data) {
00095 uint8_t *tmp;
00096 avio_close_dyn_buf(vp8->data, &tmp);
00097 av_free(tmp);
00098 vp8->data = NULL;
00099 }
00100 if ((res = avio_open_dyn_buf(&vp8->data)) < 0)
00101 return res;
00102 vp8->timestamp = *timestamp;
00103 }
00104
00105 if (!vp8->data || vp8->timestamp != *timestamp) {
00106 av_log(ctx, AV_LOG_WARNING,
00107 "Received no start marker; dropping frame\n");
00108 return AVERROR(EAGAIN);
00109 }
00110
00111 avio_write(vp8->data, buf, len);
00112
00113 if (end_packet) {
00114 int ret = ff_rtp_finalize_packet(pkt, &vp8->data, st->index);
00115 if (ret < 0)
00116 return ret;
00117 return 0;
00118 }
00119
00120 return AVERROR(EAGAIN);
00121 }
00122
00123 static PayloadContext *vp8_new_context(void)
00124 {
00125 return av_mallocz(sizeof(PayloadContext));
00126 }
00127
00128 static void vp8_free_context(PayloadContext *vp8)
00129 {
00130 if (vp8->data) {
00131 uint8_t *tmp;
00132 avio_close_dyn_buf(vp8->data, &tmp);
00133 av_free(tmp);
00134 }
00135 av_free(vp8);
00136 }
00137
00138 RTPDynamicProtocolHandler ff_vp8_dynamic_handler = {
00139 .enc_name = "VP8",
00140 .codec_type = AVMEDIA_TYPE_VIDEO,
00141 .codec_id = AV_CODEC_ID_VP8,
00142 .alloc = vp8_new_context,
00143 .free = vp8_free_context,
00144 .parse_packet = vp8_handle_packet,
00145 };