comparison rtpdec_xiph.c @ 6347:e2834a83d6a8 libavformat

rtpdec_xiph: Split packets in the depacketizer The vorbis decoder doesn't handle more than one audio frame packed into the same AVPacket, so they need to be split in the depacketizer.
author mstorsjo
date Thu, 05 Aug 2010 04:42:36 +0000
parents a90f19fbad6f
children
comparison
equal deleted inserted replaced
6346:5bd7120eb3e7 6347:e2834a83d6a8
41 */ 41 */
42 struct PayloadContext { 42 struct PayloadContext {
43 unsigned ident; ///< 24-bit stream configuration identifier 43 unsigned ident; ///< 24-bit stream configuration identifier
44 uint32_t timestamp; 44 uint32_t timestamp;
45 ByteIOContext* fragment; ///< buffer for split payloads 45 ByteIOContext* fragment; ///< buffer for split payloads
46 uint8_t *split_buf;
47 int split_pos, split_buf_len, split_buf_size;
48 int split_pkts;
46 }; 49 };
47 50
48 static PayloadContext *xiph_new_context(void) 51 static PayloadContext *xiph_new_context(void)
49 { 52 {
50 return av_mallocz(sizeof(PayloadContext)); 53 return av_mallocz(sizeof(PayloadContext));
61 } 64 }
62 65
63 static void xiph_free_context(PayloadContext * data) 66 static void xiph_free_context(PayloadContext * data)
64 { 67 {
65 free_fragment_if_needed(data); 68 free_fragment_if_needed(data);
69 av_free(data->split_buf);
66 av_free(data); 70 av_free(data);
67 } 71 }
68 72
69 static int xiph_handle_packet(AVFormatContext * ctx, 73 static int xiph_handle_packet(AVFormatContext * ctx,
70 PayloadContext * data, 74 PayloadContext * data,
74 const uint8_t * buf, int len, int flags) 78 const uint8_t * buf, int len, int flags)
75 { 79 {
76 80
77 int ident, fragmented, tdt, num_pkts, pkt_len; 81 int ident, fragmented, tdt, num_pkts, pkt_len;
78 82
83 if (!buf) {
84 if (!data->split_buf || data->split_pos + 2 > data->split_buf_len ||
85 data->split_pkts <= 0) {
86 av_log(ctx, AV_LOG_ERROR, "No more data to return\n");
87 return AVERROR_INVALIDDATA;
88 }
89 pkt_len = AV_RB16(data->split_buf + data->split_pos);
90 data->split_pos += 2;
91 if (data->split_pos + pkt_len > data->split_buf_len) {
92 av_log(ctx, AV_LOG_ERROR, "Not enough data to return\n");
93 return AVERROR_INVALIDDATA;
94 }
95 if (av_new_packet(pkt, pkt_len)) {
96 av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
97 return AVERROR(ENOMEM);
98 }
99 pkt->stream_index = st->index;
100 memcpy(pkt->data, data->split_buf + data->split_pos, pkt_len);
101 data->split_pos += pkt_len;
102 data->split_pkts--;
103 return data->split_pkts > 0;
104 }
105
79 if (len < 6) { 106 if (len < 6) {
80 av_log(ctx, AV_LOG_ERROR, "Invalid %d byte packet\n", len); 107 av_log(ctx, AV_LOG_ERROR, "Invalid %d byte packet\n", len);
81 return AVERROR_INVALIDDATA; 108 return AVERROR_INVALIDDATA;
82 } 109 }
83 110
110 137
111 buf += 6; // move past header bits 138 buf += 6; // move past header bits
112 len -= 6; 139 len -= 6;
113 140
114 if (fragmented == 0) { 141 if (fragmented == 0) {
115 // whole frame(s) 142 if (av_new_packet(pkt, pkt_len)) {
116 int i, data_len, write_len;
117 buf -= 2;
118 len += 2;
119
120 // fast first pass to calculate total length
121 for (i = 0, data_len = 0; (i < num_pkts) && (len >= 2); i++) {
122 int off = data_len + (i << 1);
123 pkt_len = AV_RB16(buf + off);
124 data_len += pkt_len;
125 len -= pkt_len + 2;
126 }
127
128 if (len < 0 || i < num_pkts) {
129 av_log(ctx, AV_LOG_ERROR,
130 "Bad packet: %d bytes left at frame %d of %d\n",
131 len, i, num_pkts);
132 return AVERROR_INVALIDDATA;
133 }
134
135 if (av_new_packet(pkt, data_len)) {
136 av_log(ctx, AV_LOG_ERROR, "Out of memory.\n"); 143 av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
137 return AVERROR(ENOMEM); 144 return AVERROR(ENOMEM);
138 } 145 }
139 pkt->stream_index = st->index; 146 pkt->stream_index = st->index;
140 147 memcpy(pkt->data, buf, pkt_len);
141 // concatenate frames 148 buf += pkt_len;
142 for (i = 0, write_len = 0; write_len < data_len; i++) { 149 len -= pkt_len;
143 pkt_len = AV_RB16(buf); 150 num_pkts--;
144 buf += 2; 151
145 memcpy(pkt->data + write_len, buf, pkt_len); 152 if (num_pkts > 0) {
146 write_len += pkt_len; 153 if (len > data->split_buf_size || !data->split_buf) {
147 buf += pkt_len; 154 av_freep(&data->split_buf);
148 } 155 data->split_buf_size = 2 * len;
149 assert(write_len == data_len); 156 data->split_buf = av_malloc(data->split_buf_size);
157 if (!data->split_buf) {
158 av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
159 av_free_packet(pkt);
160 return AVERROR(ENOMEM);
161 }
162 }
163 memcpy(data->split_buf, buf, len);
164 data->split_buf_len = len;
165 data->split_pos = 0;
166 data->split_pkts = num_pkts;
167 return 1;
168 }
150 169
151 return 0; 170 return 0;
152 171
153 } else if (fragmented == 1) { 172 } else if (fragmented == 1) {
154 // start of xiph data fragment 173 // start of xiph data fragment