Mercurial > mplayer.hg
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 } |