comparison libmpdemux/demux_asf.c @ 2310:9e059416eea6

libdemuxer...
author arpi
date Sat, 20 Oct 2001 18:49:08 +0000
parents demux_asf.c@5216f108cb4f
children 4f3e8c8ea32f
comparison
equal deleted inserted replaced
2309:3128b9d8b4ea 2310:9e059416eea6
1 // ASF file parser for DEMUXER v0.3 by A'rpi/ESP-team
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6
7 #include "config.h"
8 #include "mp_msg.h"
9 #include "help_mp.h"
10
11 #include "stream.h"
12 #include "asf.h"
13 #include "demuxer.h"
14
15
16 /*
17 * Load 16/32-bit values in little endian byte order
18 * from an unaligned address
19 */
20 #ifdef ARCH_X86
21 #define LOAD_LE32(p) (*(unsigned int*)(p))
22 #define LOAD_LE16(p) (*(unsigned short*)(p))
23 #else
24 #define LOAD_LE32(p) (((unsigned char*)(p))[0] | \
25 ((unsigned char*)(p))[1]<< 8 | \
26 ((unsigned char*)(p))[2]<<16 | \
27 ((unsigned char*)(p))[3]<<24 )
28 #define LOAD_LE16(p) (((unsigned char*)(p))[0] | \
29 ((unsigned char*)(p))[1]<<8)
30 #endif
31
32 // defined at asfheader.c:
33 extern unsigned char* asf_packet;
34 extern int asf_scrambling_h;
35 extern int asf_scrambling_w;
36 extern int asf_scrambling_b;
37 extern int asf_packetsize;
38
39
40 // based on asf file-format doc by Eugene [http://divx.euro.ru]
41
42 static void asf_descrambling(unsigned char *src,int len){
43 unsigned char *dst=malloc(len);
44 unsigned char *s2=src;
45 int i=0,x,y;
46 while(len-i>=asf_scrambling_h*asf_scrambling_w*asf_scrambling_b){
47 // mp_msg(MSGT_DEMUX,MSGL_DBG4,"descrambling! (w=%d b=%d)\n",w,asf_scrambling_b);
48 //i+=asf_scrambling_h*asf_scrambling_w;
49 for(x=0;x<asf_scrambling_w;x++)
50 for(y=0;y<asf_scrambling_h;y++){
51 memcpy(dst+i,s2+(y*asf_scrambling_w+x)*asf_scrambling_b,asf_scrambling_b);
52 i+=asf_scrambling_b;
53 }
54 s2+=asf_scrambling_h*asf_scrambling_w*asf_scrambling_b;
55 }
56 //if(i<len) memcpy(dst+i,src+i,len-i);
57 memcpy(src,dst,i);
58 free(dst);
59 }
60
61
62 static int demux_asf_read_packet(demuxer_t *demux,unsigned char *data,int len,int id,int seq,unsigned long time,unsigned short dur,int offs,int keyframe){
63 demux_stream_t *ds=NULL;
64
65 mp_dbg(MSGT_DEMUX,MSGL_DBG4,"demux_asf.read_packet: id=%d seq=%d len=%d\n",id,seq,len);
66
67 if(demux->video->id==-1)
68 if(demux->v_streams[id])
69 demux->video->id=id;
70
71 if(demux->audio->id==-1)
72 if(demux->a_streams[id])
73 demux->audio->id=id;
74
75 if(id==demux->audio->id){
76 // audio
77 ds=demux->audio;
78 if(!ds->sh){
79 ds->sh=demux->a_streams[id];
80 mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected ASF audio ID = %d\n",ds->id);
81 }
82 } else
83 if(id==demux->video->id){
84 // video
85 ds=demux->video;
86 if(!ds->sh){
87 ds->sh=demux->v_streams[id];
88 mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected ASF video ID = %d\n",ds->id);
89 }
90 }
91
92 if(ds){
93 if(ds->asf_packet){
94 if(ds->asf_seq!=seq){
95 // closed segment, finalize packet:
96 if(ds==demux->audio)
97 if(asf_scrambling_h>1 && asf_scrambling_w>1)
98 asf_descrambling(ds->asf_packet->buffer,ds->asf_packet->len);
99 ds_add_packet(ds,ds->asf_packet);
100 ds->asf_packet=NULL;
101 } else {
102 // append data to it!
103 demux_packet_t* dp=ds->asf_packet;
104 if(dp->len!=offs && offs!=-1) mp_msg(MSGT_DEMUX,MSGL_V,"warning! fragment.len=%d BUT next fragment offset=%d \n",dp->len,offs);
105 dp->buffer=realloc(dp->buffer,dp->len+len);
106 memcpy(dp->buffer+dp->len,data,len);
107 mp_dbg(MSGT_DEMUX,MSGL_DBG4,"data appended! %d+%d\n",dp->len,len);
108 dp->len+=len;
109 // we are ready now.
110 return 1;
111 }
112 }
113 // create new packet:
114 { demux_packet_t* dp;
115 if(offs>0){
116 mp_msg(MSGT_DEMUX,MSGL_V,"warning! broken fragment, %d bytes missing \n",offs);
117 return 0;
118 }
119 dp=new_demux_packet(len);
120 memcpy(dp->buffer,data,len);
121 dp->pts=time*0.001f;
122 dp->flags=keyframe;
123 // if(ds==demux->video) printf("ASF time: %8d dur: %5d \n",time,dur);
124 dp->pos=demux->filepos;
125 ds->asf_packet=dp;
126 ds->asf_seq=seq;
127 // we are ready now.
128 return 1;
129 }
130 }
131
132 return 0;
133 }
134
135 //static int num_elementary_packets100=0;
136 //static int num_elementary_packets101=0;
137
138 // return value:
139 // 0 = EOF or no stream found
140 // 1 = successfully read a packet
141 int demux_asf_fill_buffer(demuxer_t *demux){
142
143 demux->filepos=stream_tell(demux->stream);
144 if(demux->filepos>=demux->movi_end){
145 demux->stream->eof=1;
146 return 0;
147 }
148
149 stream_read(demux->stream,asf_packet,asf_packetsize);
150 if(demux->stream->eof) return 0; // EOF
151
152 if(asf_packet[0]==0x82){
153 unsigned char flags=asf_packet[3];
154 unsigned char segtype=asf_packet[4];
155 unsigned char* p=&asf_packet[5];
156 unsigned char* p_end=p+asf_packetsize;
157 unsigned long time;
158 unsigned short duration;
159 int segs=1;
160 unsigned char segsizetype=0x80;
161 int seg;
162 int padding=0;
163 int plen;
164
165 if(verbose>1){
166 int i;
167 for(i=0;i<16;i++) printf(" %02X",asf_packet[i]);
168 printf("\n");
169 }
170
171 //if(segtype!=0x5d) printf("Warning! packet[4] != 0x5d \n");
172
173 // Calculate packet size (plen):
174 if(flags&0x40){
175 // Explicit (absoulte) packet size
176 plen=LOAD_LE16(p); p+=2;
177 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"Explicit packet size specified: %d \n",plen);
178 if(plen>asf_packetsize) mp_msg(MSGT_DEMUX,MSGL_V,"Warning! plen>packetsize! (%d>%d) \n",plen,asf_packetsize);
179 if(flags&(8|16)){
180 padding=p[0];p++;
181 if(flags&16){ padding|=p[0]<<8; p++;}
182 mp_msg(MSGT_DEMUX,MSGL_V,"Warning! explicit=%d padding=%d \n",plen,asf_packetsize-padding);
183 }
184 } else {
185 // Padding (relative) size
186 if(flags&8){
187 padding=p[0];++p;
188 } else
189 if(flags&16){
190 padding=LOAD_LE16(p);p+=2;
191 }
192 plen=asf_packetsize-padding;
193 }
194
195 time = LOAD_LE32(p); p+=4;
196 duration = LOAD_LE16(p); p+=2;
197 if(flags&1){
198 segsizetype=p[0] & 0xC0;
199 segs=p[0] & 0x3F;
200 ++p;
201 }
202 mp_dbg(MSGT_DEMUX,MSGL_DBG4,"%08X: flag=%02X segs=%d pad=%d time=%ld dur=%d\n",
203 demux->filepos,flags,segs,padding,time,duration);
204 for(seg=0;seg<segs;seg++){
205 //ASF_segmhdr_t* sh;
206 unsigned char streamno;
207 unsigned char seq;
208 int len;
209 unsigned long x;
210 unsigned char type;
211 unsigned long time2;
212 int keyframe=0;
213
214 if(p>=p_end) mp_msg(MSGT_DEMUX,MSGL_V,"Warning! invalid packet 1, sig11 coming soon...\n");
215
216 if(verbose>1){
217 int i;
218 printf("seg %d:",seg);
219 for(i=0;i<16;i++) printf(" %02X",p[i]);
220 printf("\n");
221 }
222
223 streamno=p[0]&0x7F;
224 if(p[0]&0x80) keyframe=1;
225 seq=p[1];
226 p+=2;
227
228 switch(segtype){
229 case 0x55:
230 x=*((unsigned char*)p);
231 p++;
232 break;
233 case 0x59:
234 x=LOAD_LE16(p);
235 p+=2;
236 break;
237 case 0x5D:
238 x=LOAD_LE32(p);
239 p+=4;
240 break;
241 default:
242 mp_msg(MSGT_DEMUX,MSGL_V,"Warning! unknown segtype == 0x%2X \n",segtype);
243 x=0;
244 }
245
246 type=p[0]; p++; // 0x01: grouping 0x08: single
247
248 switch(type){
249 case 0x01:
250 //printf("grouping: %02X \n",p[0]);
251 ++p; // skip unknown byte
252 break;
253 case 0x08:
254 //printf("!!! obj_length = %d\n",*((unsigned long*)p));
255 p+=4;
256 time2=LOAD_LE32(p);p+=4;
257 break;
258 default:
259 mp_msg(MSGT_DEMUX,MSGL_V,"unknown segment type: 0x%02X \n",type);
260 }
261
262 if(flags&1){
263 // multiple segments
264 if(segsizetype==0x40){
265 len=*((unsigned char*)p);p++; // 1 byte
266 } else {
267 len=LOAD_LE16(p);p+=2; // 2 byte
268 }
269 } else {
270 // single segment
271 len=plen-(p-asf_packet);
272 }
273 if(len<0 || (p+len)>=p_end){
274 mp_msg(MSGT_DEMUX,MSGL_V,"ASF_parser: warning! segment len=%d\n",len);
275 }
276 mp_dbg(MSGT_DEMUX,MSGL_DBG4," seg #%d: streamno=%d seq=%d type=%02X len=%d\n",seg,streamno,seq,type,len);
277
278 switch(type){
279 case 0x01:
280 // GROUPING:
281 //printf("ASF_parser: warning! grouping (flag=1) not yet supported!\n",len);
282 //printf(" total: %d \n",len);
283 while(len>0){
284 int len2=p[0];
285 p++;
286 //printf(" group part: %d bytes\n",len2);
287 demux_asf_read_packet(demux,p,len2,streamno,seq,x,duration,-1,keyframe);
288 p+=len2;
289 len-=len2+1;
290 }
291 if(len!=0){
292 mp_msg(MSGT_DEMUX,MSGL_V,"ASF_parser: warning! groups total != len\n");
293 }
294 break;
295 case 0x08:
296 // NO GROUPING:
297 //printf("fragment offset: %d \n",sh->x);
298 demux_asf_read_packet(demux,p,len,streamno,seq,time2,duration,x,keyframe);
299 p+=len;
300 break;
301 }
302
303 } // for segs
304 return 1; // success
305 }
306
307 mp_msg(MSGT_DEMUX,MSGL_V,"%08X: UNKNOWN TYPE %02X %02X %02X %02X %02X...\n",demux->filepos,asf_packet[0],asf_packet[1],asf_packet[2],asf_packet[3],asf_packet[4]);
308 return 0;
309 }
310
311
312 #include "wine/mmreg.h"
313 #include "wine/avifmt.h"
314 #include "wine/vfw.h"
315
316 #include "codec-cfg.h"
317 #include "stheader.h"
318
319
320 void demux_seek_asf(demuxer_t *demuxer,float rel_seek_secs,int flags){
321 demux_stream_t *d_audio=demuxer->audio;
322 demux_stream_t *d_video=demuxer->video;
323 sh_audio_t *sh_audio=d_audio->sh;
324 // sh_video_t *sh_video=d_video->sh;
325
326 //FIXME: OFF_T - didn't test ASF case yet (don't have a large asf...)
327 //FIXME: reports good or bad to steve@daviesfam.org please
328
329 //================= seek in ASF ==========================
330 float p_rate=10; // packets / sec
331 off_t rel_seek_packs=(flags&2)? // FIXME: int may be enough?
332 (rel_seek_secs*(demuxer->movi_end-demuxer->movi_start)/asf_packetsize):
333 (rel_seek_secs*p_rate);
334 off_t rel_seek_bytes=rel_seek_packs*asf_packetsize;
335 off_t newpos;
336 //printf("ASF: packs: %d duration: %d \n",(int)fileh.packets,*((int*)&fileh.duration));
337 // printf("ASF_seek: %d secs -> %d packs -> %d bytes \n",
338 // rel_seek_secs,rel_seek_packs,rel_seek_bytes);
339 newpos=((flags&1)?demuxer->movi_start:demuxer->filepos)+rel_seek_bytes;
340 if(newpos<0 || newpos<demuxer->movi_start) newpos=demuxer->movi_start;
341 // printf("\r -- asf: newpos=%d -- \n",newpos);
342 stream_seek(demuxer->stream,newpos);
343
344 ds_fill_buffer(d_video);
345 if(sh_audio){
346 ds_fill_buffer(d_audio);
347 resync_audio_stream(sh_audio);
348 }
349
350 while(1){
351 if(sh_audio && !d_audio->eof){
352 float a_pts=d_audio->pts;
353 a_pts+=(ds_tell_pts(d_audio)-sh_audio->a_in_buffer_len)/(float)sh_audio->i_bps;
354 // sync audio:
355 if (d_video->pts > a_pts){
356 skip_audio_frame(sh_audio);
357 // if(!ds_fill_buffer(d_audio)) sh_audio=NULL; // skip audio. EOF?
358 continue;
359 }
360 }
361 if(d_video->flags&1) break; // found a keyframe!
362 if(!ds_fill_buffer(d_video)) break; // skip frame. EOF?
363 }
364
365
366 }
367