Mercurial > libavformat.hg
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 |