comparison libmpdemux/asfheader.c @ 18609:bb7042d74855

Patch from John Donaghy: "fix for audio and video in dvr-ms asf files"
author pacman
date Tue, 06 Jun 2006 23:34:21 +0000
parents 11c9dfbe120c
children bf04d0097971
comparison
equal deleted inserted replaced
18608:a80c7de8a4ba 18609:bb7042d74855
32 #define ASF_GUID_PREFIX_stream_header 0xB7DC0791 32 #define ASF_GUID_PREFIX_stream_header 0xB7DC0791
33 #define ASF_GUID_PREFIX_header_2_0 0xD6E229D1 33 #define ASF_GUID_PREFIX_header_2_0 0xD6E229D1
34 #define ASF_GUID_PREFIX_file_header 0x8CABDCA1 34 #define ASF_GUID_PREFIX_file_header 0x8CABDCA1
35 #define ASF_GUID_PREFIX_content_desc 0x75b22633 35 #define ASF_GUID_PREFIX_content_desc 0x75b22633
36 #define ASF_GUID_PREFIX_stream_group 0x7bf875ce 36 #define ASF_GUID_PREFIX_stream_group 0x7bf875ce
37 #define ASF_GUID_PREFIX_ext_audio_stream 0x31178C9D
38 #define ASF_GUID_PREFIX_ext_stream_embed_stream_header 0x3AFB65E2
37 39
38 /* 40 /*
39 const char asf_audio_stream_guid[16] = {0x40, 0x9e, 0x69, 0xf8, 41 const char asf_audio_stream_guid[16] = {0x40, 0x9e, 0x69, 0xf8,
40 0x4d, 0x5b, 0xcf, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b}; 42 0x4d, 0x5b, 0xcf, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b};
41 const char asf_video_stream_guid[16] = {0xc0, 0xef, 0x19, 0xbc, 43 const char asf_video_stream_guid[16] = {0xc0, 0xef, 0x19, 0xbc,
49 0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c}; 51 0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c};
50 const char asf_stream_group_guid[16] = {0xce, 0x75, 0xf8, 0x7b, 52 const char asf_stream_group_guid[16] = {0xce, 0x75, 0xf8, 0x7b,
51 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2}; 53 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2};
52 const char asf_data_chunk_guid[16] = {0x36, 0x26, 0xb2, 0x75, 54 const char asf_data_chunk_guid[16] = {0x36, 0x26, 0xb2, 0x75,
53 0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c}; 55 0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c};
56 const char asf_ext_stream_embed_stream_header[16] = {0xe2, 0x65, 0xfb, 0x3a,
57 0xef, 0x47, 0xf2, 0x40, 0xac, 0x2c, 0x70, 0xa9, 0x0d, 0x71, 0xd3, 0x43};
58 const char asf_ext_stream_audio[16] = {0x9d, 0x8c, 0x17, 0x31,
59 0xe1, 0x03, 0x28, 0x45, 0xb5, 0x82, 0x3d, 0xf9, 0xdb, 0x22, 0xf5, 0x03};
60 const char asf_ext_stream_header[16] = {0xCB, 0xA5, 0xE6, 0x14,
61 0x72, 0xC6, 0x32, 0x43, 0x83, 0x99, 0xA9, 0x69, 0x52, 0x06, 0x5B, 0x5A};
54 62
55 63
56 // the variable string is modify in this function 64 // the variable string is modify in this function
57 void pack_asf_string(char* string, int length) { 65 void pack_asf_string(char* string, int length) {
58 int i,j; 66 int i,j;
75 int i; 83 int i;
76 84
77 switch(ASF_LOAD_GUID_PREFIX(guid)){ 85 switch(ASF_LOAD_GUID_PREFIX(guid)){
78 case ASF_GUID_PREFIX_audio_stream: 86 case ASF_GUID_PREFIX_audio_stream:
79 return "guid_audio_stream"; 87 return "guid_audio_stream";
88 case ASF_GUID_PREFIX_ext_audio_stream:
89 return "guid_ext_audio_stream";
90 case ASF_GUID_PREFIX_ext_stream_embed_stream_header:
91 return "guid_ext_stream_embed_stream_header";
80 case ASF_GUID_PREFIX_video_stream: 92 case ASF_GUID_PREFIX_video_stream:
81 return "guid_video_stream"; 93 return "guid_video_stream";
82 case ASF_GUID_PREFIX_audio_conceal_none: 94 case ASF_GUID_PREFIX_audio_conceal_none:
83 return "guid_audio_conceal_none"; 95 return "guid_audio_conceal_none";
84 case ASF_GUID_PREFIX_audio_conceal_interleave: 96 case ASF_GUID_PREFIX_audio_conceal_interleave:
142 return i + 16 + 8; // point after guid + length 154 return i + 16 + 8; // point after guid + length
143 } 155 }
144 return -1; 156 return -1;
145 } 157 }
146 158
159 static int find_backwards_asf_guid(char *buf, const char *guid, int cur_pos)
160 {
161 int i;
162 for (i=cur_pos-16; i>0; i--) {
163 if (memcmp(&buf[i], guid, 16) == 0)
164 return i + 16 + 8; // point after guid + length
165 }
166 return -1;
167 }
168
169 static int asf_init_audio_stream(demuxer_t *demuxer,struct asf_priv* asf, sh_audio_t* sh_audio, ASF_stream_header_t *streamh, int *ppos, uint8_t** buf, char *hdr, unsigned int hdr_len)
170 {
171 uint8_t *buffer = *buf;
172 int pos = *ppos;
173
174 sh_audio->wf=calloc((streamh->type_size<sizeof(WAVEFORMATEX))?sizeof(WAVEFORMATEX):streamh->type_size,1);
175 memcpy(sh_audio->wf,buffer,streamh->type_size);
176 le2me_WAVEFORMATEX(sh_audio->wf);
177 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_audio->wf,MSGL_V);
178 if(ASF_LOAD_GUID_PREFIX(streamh->concealment)==ASF_GUID_PREFIX_audio_conceal_interleave){
179 buffer = &hdr[pos];
180 pos += streamh->stream_size;
181 if (pos > hdr_len) return 0;
182 asf->scrambling_h=buffer[0];
183 asf->scrambling_w=(buffer[2]<<8)|buffer[1];
184 asf->scrambling_b=(buffer[4]<<8)|buffer[3];
185 if(asf->scrambling_b>0){
186 asf->scrambling_w/=asf->scrambling_b;
187 }
188 } else {
189 asf->scrambling_b=asf->scrambling_h=asf->scrambling_w=1;
190 }
191 mp_msg(MSGT_HEADER,MSGL_V,"ASF: audio scrambling: %d x %d x %d\n",asf->scrambling_h,asf->scrambling_w,asf->scrambling_b);
192 return 1;
193 }
194
147 int read_asf_header(demuxer_t *demuxer,struct asf_priv* asf){ 195 int read_asf_header(demuxer_t *demuxer,struct asf_priv* asf){
148 int hdr_len = asf->header.objh.size - sizeof(asf->header); 196 int hdr_len = asf->header.objh.size - sizeof(asf->header);
149 char *hdr = NULL; 197 char *hdr = NULL;
150 char guid_buffer[16]; 198 char guid_buffer[16];
151 int pos, start = stream_tell(demuxer->stream); 199 int pos, start = stream_tell(demuxer->stream);
154 int video_streams=0; 202 int video_streams=0;
155 uint16_t stream_count=0; 203 uint16_t stream_count=0;
156 int best_video = -1; 204 int best_video = -1;
157 int best_audio = -1; 205 int best_audio = -1;
158 uint64_t data_len; 206 uint64_t data_len;
207 ASF_stream_header_t *streamh;
208 uint8_t *buffer;
209 int audio_pos=0;
159 210
160 if(hdr_len < 0) { 211 if(hdr_len < 0) {
161 mp_msg(MSGT_HEADER, MSGL_FATAL, "Header size is too small.\n"); 212 mp_msg(MSGT_HEADER, MSGL_FATAL, "Header size is too small.\n");
162 return 0; 213 return 0;
163 } 214 }
177 if (stream_eof(demuxer->stream)) { 228 if (stream_eof(demuxer->stream)) {
178 mp_msg(MSGT_HEADER, MSGL_FATAL, MSGTR_MPDEMUX_ASFHDR_EOFWhileReadingHeader); 229 mp_msg(MSGT_HEADER, MSGL_FATAL, MSGTR_MPDEMUX_ASFHDR_EOFWhileReadingHeader);
179 goto err_out; 230 goto err_out;
180 } 231 }
181 232
233 if ((pos = find_asf_guid(hdr, asf_ext_stream_audio, pos, hdr_len)) >= 0)
234 {
235 // Special case: found GUID for dvr-ms audio.
236 // Now skip back to associated stream header.
237 int sh_pos=0;
238
239 sh_pos = find_backwards_asf_guid(hdr, asf_stream_header_guid, pos);
240
241 if (sh_pos > 0) {
242 mp_msg(MSGT_HEADER, MSGL_V, "read_asf_header found dvr-ms audio stream header pos=%d\n", sh_pos);
243 // found audio stream header - following code reads header and
244 // initializes audio stream.
245 audio_pos = pos - 16 - 8;
246 streamh = (ASF_stream_header_t *)&hdr[sh_pos];
247 le2me_ASF_stream_header_t(streamh);
248 audio_pos += 64; //16+16+4+4+4+16+4;
249 buffer = &hdr[audio_pos];
250 sh_audio_t* sh_audio=new_sh_audio(demuxer,streamh->stream_no & 0x7F);
251 ++audio_streams;
252 if (!asf_init_audio_stream(demuxer, asf, sh_audio, streamh, &audio_pos, &buffer, hdr, hdr_len))
253 goto len_err_out;
254 }
255 }
182 // find stream headers 256 // find stream headers
183 pos = 0; 257 // only reset pos if we didnt find dvr_ms audio stream
258 // if we did find it then we want to avoid reading its header twice
259 if (audio_pos == 0)
260 pos = 0;
261
184 while ((pos = find_asf_guid(hdr, asf_stream_header_guid, pos, hdr_len)) >= 0) 262 while ((pos = find_asf_guid(hdr, asf_stream_header_guid, pos, hdr_len)) >= 0)
185 { 263 {
186 ASF_stream_header_t *streamh = (ASF_stream_header_t *)&hdr[pos]; 264 streamh = (ASF_stream_header_t *)&hdr[pos];
187 uint8_t *buffer;
188 pos += sizeof(ASF_stream_header_t); 265 pos += sizeof(ASF_stream_header_t);
189 if (pos > hdr_len) goto len_err_out; 266 if (pos > hdr_len) goto len_err_out;
190 le2me_ASF_stream_header_t(streamh); 267 le2me_ASF_stream_header_t(streamh);
191 mp_msg(MSGT_HEADER, MSGL_V, "stream type: %s\n", 268 mp_msg(MSGT_HEADER, MSGL_V, "stream type: %s\n",
192 asf_chunk_type(streamh->type)); 269 asf_chunk_type(streamh->type));
204 if (pos > hdr_len) goto len_err_out; 281 if (pos > hdr_len) goto len_err_out;
205 switch(ASF_LOAD_GUID_PREFIX(streamh->type)){ 282 switch(ASF_LOAD_GUID_PREFIX(streamh->type)){
206 case ASF_GUID_PREFIX_audio_stream: { 283 case ASF_GUID_PREFIX_audio_stream: {
207 sh_audio_t* sh_audio=new_sh_audio(demuxer,streamh->stream_no & 0x7F); 284 sh_audio_t* sh_audio=new_sh_audio(demuxer,streamh->stream_no & 0x7F);
208 ++audio_streams; 285 ++audio_streams;
209 sh_audio->wf=calloc((streamh->type_size<sizeof(WAVEFORMATEX))?sizeof(WAVEFORMATEX):streamh->type_size,1); 286 if (!asf_init_audio_stream(demuxer, asf, sh_audio, streamh, &pos, &buffer, hdr, hdr_len))
210 memcpy(sh_audio->wf,buffer,streamh->type_size); 287 goto len_err_out;
211 le2me_WAVEFORMATEX(sh_audio->wf);
212 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_audio->wf,MSGL_V);
213 if(ASF_LOAD_GUID_PREFIX(streamh->concealment)==ASF_GUID_PREFIX_audio_conceal_interleave){
214 buffer = &hdr[pos];
215 pos += streamh->stream_size;
216 if (pos > hdr_len) goto len_err_out;
217 asf->scrambling_h=buffer[0];
218 asf->scrambling_w=(buffer[2]<<8)|buffer[1];
219 asf->scrambling_b=(buffer[4]<<8)|buffer[3];
220 if(asf->scrambling_b>0){
221 asf->scrambling_w/=asf->scrambling_b;
222 }
223 } else {
224 asf->scrambling_b=asf->scrambling_h=asf->scrambling_w=1;
225 }
226 mp_msg(MSGT_HEADER,MSGL_V,"ASF: audio scrambling: %d x %d x %d\n",asf->scrambling_h,asf->scrambling_w,asf->scrambling_b);
227 //if(demuxer->audio->id==-1) demuxer->audio->id=streamh.stream_no & 0x7F; 288 //if(demuxer->audio->id==-1) demuxer->audio->id=streamh.stream_no & 0x7F;
228 break; 289 break;
229 } 290 }
230 case ASF_GUID_PREFIX_video_stream: { 291 case ASF_GUID_PREFIX_video_stream: {
231 sh_video_t* sh_video=new_sh_video(demuxer,streamh->stream_no & 0x7F); 292 sh_video_t* sh_video=new_sh_video(demuxer,streamh->stream_no & 0x7F);
233 ++video_streams; 294 ++video_streams;
234 // sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize); 295 // sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize);
235 sh_video->bih=calloc((len<sizeof(BITMAPINFOHEADER))?sizeof(BITMAPINFOHEADER):len,1); 296 sh_video->bih=calloc((len<sizeof(BITMAPINFOHEADER))?sizeof(BITMAPINFOHEADER):len,1);
236 memcpy(sh_video->bih,&buffer[4+4+1+2],len); 297 memcpy(sh_video->bih,&buffer[4+4+1+2],len);
237 le2me_BITMAPINFOHEADER(sh_video->bih); 298 le2me_BITMAPINFOHEADER(sh_video->bih);
238 if (sh_video->bih->biCompression == mmioFOURCC('D', 'V', 'R', ' ')) 299 if (sh_video->bih->biCompression == mmioFOURCC('D', 'V', 'R', ' ')) {
239 mp_msg(MSGT_DEMUXER, MSGL_WARN, MSGTR_MPDEMUX_ASFHDR_DVRWantsLibavformat); 300 //mp_msg(MSGT_DEMUXER, MSGL_WARN, MSGTR_MPDEMUX_ASFHDR_DVRWantsLibavformat);
240 //sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale; 301 //sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale;
241 //sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate; 302 //sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
303 asf->asf_frame_state=-1;
304 asf->asf_frame_start_found=0;
305 asf->asf_is_dvr_ms=1;
306 } else asf->asf_is_dvr_ms=0;
242 if( mp_msg_test(MSGT_DEMUX,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V); 307 if( mp_msg_test(MSGT_DEMUX,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V);
243 //asf_video_id=streamh.stream_no & 0x7F; 308 //asf_video_id=streamh.stream_no & 0x7F;
244 //if(demuxer->video->id==-1) demuxer->video->id=streamh.stream_no & 0x7F; 309 //if(demuxer->video->id==-1) demuxer->video->id=streamh.stream_no & 0x7F;
245 break; 310 break;
246 } 311 }