23 |
23 |
|
24 |
24 |
const uint8_t *avc_find_startcode(const uint8_t *p, const uint8_t *end)
|
25 |
25 |
{
|
26 |
|
const uint8_t *a = p + 4 - ((long)p & 3);
|
27 |
|
|
28 |
|
for( end -= 3; p < a && p < end; p++ ) {
|
29 |
|
if( p[0] == 0 && p[1] == 0 && p[2] == 1 )
|
30 |
|
return p;
|
31 |
|
}
|
32 |
|
|
33 |
|
for( end -= 3; p < end; p += 4 ) {
|
34 |
|
uint32_t x = *(const uint32_t*)p;
|
35 |
|
// if( (x - 0x01000100) & (~x) & 0x80008000 ) // little endian
|
36 |
|
// if( (x - 0x00010001) & (~x) & 0x00800080 ) // big endian
|
37 |
|
if( (x - 0x01010101) & (~x) & 0x80808080 ) { // generic
|
38 |
|
if( p[1] == 0 ) {
|
39 |
|
if( p[0] == 0 && p[2] == 1 )
|
40 |
|
return p-1;
|
41 |
|
if( p[2] == 0 && p[3] == 1 )
|
42 |
|
return p;
|
43 |
|
}
|
44 |
|
if( p[3] == 0 ) {
|
45 |
|
if( p[2] == 0 && p[4] == 1 )
|
46 |
|
return p+1;
|
47 |
|
if( p[4] == 0 && p[5] == 1 )
|
48 |
|
return p+2;
|
49 |
|
}
|
50 |
|
}
|
51 |
|
}
|
52 |
|
|
53 |
|
for( end += 3; p < end; p++ ) {
|
54 |
|
if( p[0] == 0 && p[1] == 0 && p[2] == 1 )
|
55 |
|
return p;
|
56 |
|
}
|
57 |
|
|
58 |
|
return end + 3;
|
|
26 |
int i;
|
|
27 |
|
|
28 |
uint32_t sc=0xFFFFFFFF;
|
|
29 |
size_t len = (end -p)+1;
|
|
30 |
for (i=0;i<len;i++)
|
|
31 |
{
|
|
32 |
sc = (sc <<8) | p[i];
|
|
33 |
if((sc & 0xffffff00) == 0x00000100) {
|
|
34 |
return p+i-3;
|
|
35 |
}
|
|
36 |
|
|
37 |
}
|
|
38 |
return end;
|
59 |
39 |
}
|
60 |
|
|
61 |
40 |
int avc_parse_nal_units(ByteIOContext *pb, const uint8_t *buf_in, int size)
|
62 |
41 |
{
|
63 |
42 |
const uint8_t *p = buf_in;
|
64 |
43 |
const uint8_t *end = p + size;
|
65 |
|
const uint8_t *nal_start, *nal_end, *b;
|
|
44 |
const uint8_t *nal_start, *nal_end;
|
66 |
45 |
|
67 |
|
printf("CONVERT SIZE %d\n", size);
|
|
46 |
//printf("CONVERT SIZE %d\n", size);
|
68 |
47 |
|
69 |
48 |
size = 0;
|
70 |
49 |
nal_start = avc_find_startcode(p, end);
|
71 |
50 |
while (nal_start < end) {
|
72 |
51 |
while(!*(nal_start++));
|
73 |
52 |
nal_end = avc_find_startcode(nal_start, end);
|
74 |
|
printf("%4d bytes %5d : %d\n", nal_end - nal_start,
|
|
53 |
/*printf("%4d bytes %5d : %d\n", nal_end - nal_start,
|
75 |
54 |
nal_start - buf_in,
|
76 |
|
nal_end - buf_in);
|
|
55 |
nal_end - buf_in);*/
|
77 |
56 |
|
78 |
57 |
int l = nal_end - nal_start;
|
79 |
58 |
|
80 |
|
b = nal_start;
|
81 |
|
while(l > 3 && !(b[l-3] | b[l-2] | b[l-1]))
|
82 |
|
l--;
|
83 |
|
put_be32(pb, l);
|
84 |
|
put_buffer(pb, nal_start, l);
|
85 |
|
size += 4 + l;
|
|
59 |
if (l) {
|
|
60 |
put_be32(pb, l);
|
|
61 |
put_buffer(pb, nal_start, l);
|
|
62 |
size += 4 + l;
|
|
63 |
}
|
86 |
64 |
nal_start = nal_end;
|
87 |
65 |
}
|
88 |
66 |
printf("size=%d\n", size);
|
... | ... | |
125 |
103 |
if (RB32(data) == 0x00000001 ||
|
126 |
104 |
RB24(data) == 0x000001) {
|
127 |
105 |
uint8_t *buf=NULL, *end, *start;
|
128 |
|
uint32_t sps_size=0, pps_size=0;
|
129 |
|
uint8_t *sps=0, *pps=0;
|
|
106 |
uint32_t *sps_size_array=0, *pps_size_array=0;
|
|
107 |
uint32_t pps_count=0,sps_count=0;
|
|
108 |
uint8_t **sps_array=0, **pps_array=0;
|
|
109 |
int i;
|
130 |
110 |
|
131 |
111 |
int ret = avc_parse_nal_units_buf(data, &buf, &len);
|
132 |
112 |
if (ret < 0)
|
... | ... | |
141 |
121 |
size = RB32(buf);
|
142 |
122 |
nal_type = buf[4] & 0x1f;
|
143 |
123 |
if (nal_type == 7) { /* SPS */
|
144 |
|
sps = buf + 4;
|
145 |
|
sps_size = size;
|
|
124 |
sps_array = realloc(sps_array,sizeof(uint8_t*)*(sps_count+1));
|
|
125 |
sps_size_array = realloc(sps_size_array,sizeof(uint32_t)*(sps_count+1));
|
|
126 |
sps_array[sps_count] = buf + 4;
|
|
127 |
sps_size_array[sps_count] = size;
|
|
128 |
sps_count++;
|
146 |
129 |
} else if (nal_type == 8) { /* PPS */
|
147 |
|
pps = buf + 4;
|
148 |
|
pps_size = size;
|
|
130 |
pps_size_array = realloc(pps_size_array,sizeof(uint32_t)*(pps_count+1));
|
|
131 |
pps_array = realloc(pps_array,sizeof (uint8_t*)*(pps_count+1));
|
|
132 |
pps_array[pps_count] = buf + 4;
|
|
133 |
pps_size_array[pps_count] = size;
|
|
134 |
pps_count++;
|
149 |
135 |
}
|
150 |
136 |
buf += size + 4;
|
151 |
137 |
}
|
152 |
|
if(!sps || !pps) {
|
|
138 |
if(!sps_count || !pps_count) {
|
153 |
139 |
av_free(start);
|
|
140 |
if (sps_count)
|
|
141 |
free(sps_array);
|
|
142 |
if (pps_count)
|
|
143 |
free(pps_array);
|
154 |
144 |
return -1;
|
155 |
145 |
}
|
156 |
146 |
|
157 |
147 |
put_byte(pb, 1); /* version */
|
158 |
|
put_byte(pb, sps[1]); /* profile */
|
159 |
|
put_byte(pb, sps[2]); /* profile compat */
|
160 |
|
put_byte(pb, sps[3]); /* level */
|
|
148 |
put_byte(pb, sps_array[0][1]); /* profile */
|
|
149 |
put_byte(pb, sps_array[0][2]); /* profile compat */
|
|
150 |
put_byte(pb, sps_array[0][3]); /* level */
|
161 |
151 |
put_byte(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */
|
162 |
|
put_byte(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */
|
|
152 |
put_byte(pb, 0xe0+sps_count); /* 3 bits reserved (111) + 5 bits number of sps (00001) */
|
|
153 |
for (i=0;i<sps_count;i++) {
|
|
154 |
put_be16(pb, sps_size_array[i]);
|
|
155 |
put_buffer(pb, sps_array[i], sps_size_array[i]);
|
|
156 |
}
|
163 |
157 |
|
164 |
|
put_be16(pb, sps_size);
|
165 |
|
put_buffer(pb, sps, sps_size);
|
166 |
|
put_byte(pb, 1); /* number of pps */
|
167 |
|
put_be16(pb, pps_size);
|
168 |
|
put_buffer(pb, pps, pps_size);
|
|
158 |
put_byte(pb, pps_count); /* number of pps */
|
|
159 |
for (i=0;i<pps_count;i++) {
|
|
160 |
put_be16(pb, pps_size_array[i]);
|
|
161 |
put_buffer(pb, pps_array[i], pps_size_array[i]);
|
|
162 |
}
|
169 |
163 |
av_free(start);
|
|
164 |
|
|
165 |
if (sps_count)
|
|
166 |
free(sps_array);
|
|
167 |
if (pps_count)
|
|
168 |
free(pps_array);
|
170 |
169 |
} else {
|
171 |
170 |
put_buffer(pb, data, len);
|
172 |
171 |
}
|
... | ... | |
180 |
179 |
th_pkt_t *
|
181 |
180 |
avc_convert_pkt(th_pkt_t *src)
|
182 |
181 |
{
|
|
182 |
uint8_t *new_payload=0;
|
|
183 |
int32_t new_payload_len=0;
|
183 |
184 |
ByteIOContext *payload, *headers;
|
184 |
185 |
|
185 |
186 |
th_pkt_t *pkt = malloc(sizeof(th_pkt_t));
|
186 |
187 |
*pkt = *src;
|
187 |
188 |
pkt->pkt_refcount = 1;
|
|
189 |
pkt->pkt_header = NULL;
|
|
190 |
pkt->pkt_payload = NULL;
|
|
191 |
|
|
192 |
pkt->pkt_payload = malloc(sizeof(pktbuf_t));
|
|
193 |
pkt->pkt_payload->pb_refcount=1;
|
|
194 |
if (src->pkt_header) {
|
|
195 |
uint8_t *privateData;
|
|
196 |
int32_t privateDataLen;
|
|
197 |
url_open_dyn_buf(&headers);
|
|
198 |
isom_write_avcc(headers, pktbuf_ptr(src->pkt_header), pktbuf_len(src->pkt_header));
|
|
199 |
privateDataLen = url_close_dyn_buf(headers, &privateData);
|
|
200 |
hexdump(" AVC before : ", pktbuf_ptr(src->pkt_header), pktbuf_len(src->pkt_header));
|
|
201 |
hexdump(" AVC after : ", privateData, privateDataLen);
|
|
202 |
|
|
203 |
pkt->pkt_header = pktbuf_make(privateData, privateDataLen);
|
|
204 |
}
|
188 |
205 |
|
189 |
206 |
url_open_dyn_buf(&payload);
|
190 |
|
avc_parse_nal_units(payload, pkt->pkt_payload, pkt->pkt_payloadlen);
|
|
207 |
if (src->pkt_header)
|
|
208 |
avc_parse_nal_units(payload, pktbuf_ptr(src->pkt_header), pktbuf_len(src->pkt_header));
|
|
209 |
avc_parse_nal_units(payload, pktbuf_ptr(src->pkt_payload), pktbuf_len(src->pkt_payload));
|
191 |
210 |
|
192 |
|
pkt->pkt_payloadlen = url_close_dyn_buf(payload, &pkt->pkt_payload);
|
|
211 |
new_payload_len = url_close_dyn_buf(payload, &new_payload);
|
193 |
212 |
|
194 |
|
if(pkt->pkt_globaldata) {
|
195 |
|
url_open_dyn_buf(&headers);
|
196 |
|
|
197 |
|
isom_write_avcc(headers, pkt->pkt_globaldata, pkt->pkt_globaldata_len);
|
198 |
|
pkt->pkt_globaldata_len = url_close_dyn_buf(headers, &pkt->pkt_globaldata);
|
199 |
|
|
200 |
|
hexdump("annexB: ", src->pkt_globaldata, src->pkt_globaldata_len);
|
201 |
|
hexdump(" AVC: ", pkt->pkt_globaldata, pkt->pkt_globaldata_len);
|
202 |
|
|
203 |
|
|
204 |
|
}
|
|
213 |
pkt->pkt_payload = pktbuf_make(new_payload,new_payload_len);
|
205 |
214 |
pkt_ref_dec(src);
|
206 |
215 |
return pkt;
|
207 |
216 |
}
|