1 /** *************************************************************************
2 \file ADM_asf.cpp
3 \brief ASF/WMV demuxer
4 copyright : (C) 2006/2009 by mean
5 email : fixounet@free.fr
6 ***************************************************************************/
7
8 /***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17 #include "ADM_default.h"
18 #include "ADM_Video.h"
19 #include "ADM_assert.h"
20
21 #include "fourcc.h"
22 #include "DIA_coreToolkit.h"
23 #include "ADM_asf.h"
24 #include "ADM_asfPacket.h"
25
26 #if 0
27 #define aprintf printf
28 #else
29 #define aprintf(...) {}
30 #endif
31
32 /**
33 \fn getAudioInfo
34 */
getAudioInfo(uint32_t i)35 WAVHeader *asfHeader::getAudioInfo(uint32_t i )
36 {
37 if(!_nbAudioTrack) return NULL;
38
39 ADM_assert(i<_nbAudioTrack);
40 if(NULL==_audioAccess) return NULL;
41 return &(_allAudioTracks[i].wavHeader);
42 }
43 /**
44 \fn getAudioStream
45 */
getAudioStream(uint32_t i,ADM_audioStream ** audio)46 uint8_t asfHeader::getAudioStream(uint32_t i,ADM_audioStream **audio)
47 {
48 *audio=NULL;
49 if(!_nbAudioTrack) return true;
50 ADM_assert(i<_nbAudioTrack);
51 *audio=_audioStreams[i];
52 return 1;
53 }
54 /**
55 \fn getNbAudioStreams
56 */
getNbAudioStreams(void)57 uint8_t asfHeader::getNbAudioStreams(void)
58 {
59 return _nbAudioTrack;
60 }
61
62 /**
63 \fn Dump
64 */
65
Dump(void)66 void asfHeader::Dump(void)
67 {
68
69 printf("*********** ASF INFO***********\n");
70 }
71
72 /**
73 \fn close
74 */
75
close(void)76 uint8_t asfHeader::close(void)
77 {
78 if (_fd)
79 fclose(_fd);
80
81 _fd=NULL;
82
83 if(_videoExtraData)
84 {
85 delete [] _videoExtraData;
86 _videoExtraData=NULL;
87 }
88 if(myName)
89 {
90 ADM_dealloc(myName);
91 myName=NULL;
92 }
93 if(_videoExtraData)
94 {
95 delete [] _videoExtraData;
96 _videoExtraData=NULL;
97 }
98
99 if(_packet)
100 delete _packet;
101 _packet=NULL;
102
103 for(int i=0;i<_nbAudioTrack;i++)
104 {
105 asfAudioTrak *trk=&(_allAudioTracks[i]);
106 if(trk->extraData) delete [] trk->extraData;
107 trk->extraData=NULL;
108 delete _audioAccess[i];
109 _audioAccess[i]=NULL;
110 delete _audioStreams[i];
111 _audioStreams[i]=NULL;
112 }
113 freeQueue(&readQueue);
114 freeQueue(&storageQueue);
115 return 1;
116 }
117 /**
118 \fn asfHeader
119 */
120
121
asfHeader(void)122 asfHeader::asfHeader( void ) : vidHeader()
123 {
124 _fd=NULL;
125 _videoIndex=-1;
126 myName=NULL;
127 _packetSize=0;
128 _videoStreamId=0;
129 nbImage=0;
130
131 _packet=NULL;
132 _nbPackets=0;
133 memset(&(_allAudioTracks[0]),0,sizeof(_allAudioTracks));
134 memset(&(_audioAccess[0]),0,sizeof(_audioAccess));
135 memset(&(_audioStreams[0]),0,sizeof(_audioStreams));
136 _nbAudioTrack=0;
137 _videostream.dwRate=0;
138 _shiftUs=0;
139
140 }
141 /**
142 \fn ~ asfHeader
143 */
144
~asfHeader()145 asfHeader::~asfHeader( )
146 {
147 close();
148 }
149 /**
150 \fn open
151 */
152
open(const char * name)153 uint8_t asfHeader::open(const char *name)
154 {
155 _fd=ADM_fopen(name,"rb");
156 if(!_fd)
157 {
158 GUI_Error_HIG(QT_TRANSLATE_NOOP("asfdemuxer","File Error."),QT_TRANSLATE_NOOP("asfdemuxer","Cannot open file\n"));
159 return 0;
160 }
161 myName=ADM_strdup(name);
162 if(!getHeaders())
163 {
164 return 0;
165 }
166 ADM_info("Stream Video: index=%d, sid=%d\n",(int)_videoIndex,(int)_videoStreamId);
167 for(int i=0;i<_nbAudioTrack;i++)
168 ADM_info("Stream Audio: index=%d, sid=%d\n",
169 (int)_allAudioTracks[i].streamIndex,(int)_allAudioTracks[i].streamIndex);
170 uint8_t r=buildIndex();
171 switch(r)
172 {
173 case 0:
174 ADM_error("No images found \n");
175 return r;
176 case ADM_IGN:
177 ADM_warning("Indexing cancelled by user after %" PRIu32" images\n",nbImage);
178 return r;
179 default:
180 break;
181 }
182 fseeko(_fd,_dataStartOffset,SEEK_SET);
183 _packet=new asfPacket(_fd,_nbPackets,_packetSize,&readQueue,&storageQueue,_dataStartOffset);
184 curSeq=1;
185 for(int i=0;i<_nbAudioTrack;i++)
186 {
187 _audioAccess[i]=new asfAudioAccess(this,i);
188 _audioStreams[i]=ADM_audioCreateStream(&(_allAudioTracks[i].wavHeader), _audioAccess[i]);
189 }
190 return 1;
191 }
192 /**
193 \fn setFlag
194 */
195
setFlag(uint32_t frame,uint32_t flags)196 uint8_t asfHeader::setFlag(uint32_t frame,uint32_t flags)
197 {
198 ADM_assert(frame<nbImage);
199 _index[frame].flags=flags;
200 return 1;
201 }
202 /**
203 \fn getFlags
204 */
205
getFlags(uint32_t frame,uint32_t * flags)206 uint32_t asfHeader::getFlags(uint32_t frame,uint32_t *flags)
207 {
208 if(frame>=nbImage) return 0;
209 if(!frame) *flags=AVI_KEY_FRAME;
210 else
211 *flags=_index[frame].flags;
212 return 1;
213 }
214 /**
215 \fn getFrameSize
216 */
getFrameSize(uint32_t frame,uint32_t * size)217 uint8_t asfHeader::getFrameSize(uint32_t frame,uint32_t *size)
218 {
219 *size=0;
220 if(frame>=nbImage) return 0;
221 *size=_index[frame].frameLen;
222 return true;
223 }
224 /**
225 \fn getTime
226 */
getTime(uint32_t frameNum)227 uint64_t asfHeader::getTime(uint32_t frameNum)
228 {
229 if(frameNum>=nbImage) return ADM_NO_PTS;
230 return _index[frameNum].pts; // ??PTS??
231 }
232 /**
233 \fn getTime
234 */
235
getVideoDuration(void)236 uint64_t asfHeader::getVideoDuration(void)
237 {
238 return _duration;
239 }
240 /**
241 \fn getTime
242 */
243
getPtsDts(uint32_t frame,uint64_t * pts,uint64_t * dts)244 bool asfHeader::getPtsDts(uint32_t frame,uint64_t *pts,uint64_t *dts)
245 {
246 if(frame>=nbImage) return false;
247 *pts=_index[frame].pts;
248 *dts=_index[frame].dts;
249 return true;
250 }
251 /**
252 \fn getTime
253 */
254
setPtsDts(uint32_t frame,uint64_t pts,uint64_t dts)255 bool asfHeader::setPtsDts(uint32_t frame,uint64_t pts,uint64_t dts)
256 {
257 if(frame>=nbImage) return false;
258 _index[frame].pts=pts;
259 _index[frame].dts=dts;;
260 return true;
261 }
262 /**
263 \fn getFrame
264 */
getFrame(uint32_t framenum,ADMCompressedImage * img)265 uint8_t asfHeader::getFrame(uint32_t framenum,ADMCompressedImage *img)
266 {
267 img->dataLength=0;
268 img->flags=AVI_KEY_FRAME;
269 uint32_t len=0;
270 if(framenum>=nbImage)
271 {
272 printf("[ASF] Going out of bound %u %u\n",framenum, nbImage);
273 return 0;
274 }
275 if(!_index[framenum].frameLen)
276 {
277 goto gotcha;
278 }
279 // In case curSeq is stored as one byte..
280 curSeq&=0xff;
281 //
282
283 aprintf("Framenum %u len: %u curSeq %u frameSeq=%u packetnb=%u \n",
284 framenum,_index[framenum].frameLen,curSeq,
285 _index[framenum].segNb,_index[framenum].packetNb);
286 // Seeking ?
287 if(_index[framenum].segNb!=curSeq || _index[framenum].segNb==1)
288 {
289 aprintf("Seeking.. curseq:%u wanted seq:%u packet=%" PRIu64"\n",curSeq,_index[framenum].segNb,_index[framenum].packetNb);
290 if(!_packet->goToPacket(_index[framenum].packetNb))
291 {
292 printf("[ASF] Cannot seek to frame %u\n",framenum);
293 return 0;
294 }
295 _packet->purge();
296 curSeq=_index[framenum].segNb;
297 printf("Seeking done, starting at seq=%u\n",curSeq);
298 }
299
300
301 len=0;
302 uint32_t delta;
303 while(1)
304 {
305 while(readQueue.size())
306 {
307 asfBit *bit;
308 bit=readQueue.front();
309 readQueue.pop_front();
310 aprintf(">found packet of size %d seq %d, while curseq =%d wanted seg=%u current offset=%u, packet=%u\n",
311 bit->len,bit->sequence,curSeq,_index[framenum].segNb,len,bit->packet);
312 // Here it is tricky
313 // if len==0 we are reading the first part of our frame
314 // The packet may starts with segments from the previous frame
315 // discard them
316 // Delta is just a security as it should be slightly >10
317 delta=256+bit->sequence-_index[framenum].segNb;
318 delta &=0xff;
319 if(!len) // Starting a new frame
320 {
321 if(_index[framenum].segNb != bit->sequence )
322 {
323 aprintf("Dropping seq=%u too old for %u delta %d\n",
324 bit->sequence,_index[framenum].segNb,delta);
325 storageQueue.push_back(bit);
326 bit=NULL;
327 if(delta<230)
328 {
329 printf("[ASF] Very suspicious delta :%" PRIu32"\n",delta);
330 }
331 continue;
332 }
333 // We have found our first chunk
334 curSeq=bit->sequence;
335 memcpy(img->data,bit->data,bit->len);
336 len=bit->len;
337 delete[] bit->data;
338 delete bit;
339 continue;
340 }
341 // Continuing a frame
342 // If the seq number is different it is the beginning of a new frame
343 if(bit->sequence!=curSeq )
344 {
345 aprintf("New sequence %u->%u while loading %u frame\n",curSeq,bit->sequence,framenum);
346 img->dataLength=len;
347 readQueue.push_front(bit);
348 curSeq=bit->sequence;
349 goto gotcha;
350 }
351 // still same sequence ...add
352 memcpy(img->data+len,bit->data,bit->len);
353 len+=bit->len;
354 storageQueue.push_back(bit);
355 bit=NULL;
356 }
357 if(!_packet->nextPacket(_videoStreamId))
358 {
359 printf("[ASF] Packet Error\n");
360 return 0;
361 }
362 _packet->skipPacket();
363 }
364 gotcha:
365
366 img->dataLength=len;
367 img->demuxerDts=_index[framenum].dts;
368 img->demuxerPts=_index[framenum].pts;
369 img->flags=_index[framenum].flags;
370 if(len!=_index[framenum].frameLen)
371 {
372 ADM_error("[ASF] Frame=%u :-> Mismatch found len : %u expected %u\n",framenum,len, _index[framenum].frameLen);
373 }
374 aprintf(">>Len %d seq %d\n",len,curSeq);
375 return 1;
376 }
377 //EOF
378