comparison libmpdemux/asfheader.c @ 21610:05a8a034d9aa

ASF aspect support via metadata reading. Patch by Zuxy Meng (zuxy meng (at) gmail.com) with some simplifications by me.
author reimar
date Fri, 15 Dec 2006 21:51:20 +0000
parents f91f04764311
children fb4bb5aed0cf
comparison
equal deleted inserted replaced
21609:3452c36a7fe2 21610:05a8a034d9aa
58 0xef, 0x47, 0xf2, 0x40, 0xac, 0x2c, 0x70, 0xa9, 0x0d, 0x71, 0xd3, 0x43}; 58 0xef, 0x47, 0xf2, 0x40, 0xac, 0x2c, 0x70, 0xa9, 0x0d, 0x71, 0xd3, 0x43};
59 const char asf_ext_stream_audio[16] = {0x9d, 0x8c, 0x17, 0x31, 59 const char asf_ext_stream_audio[16] = {0x9d, 0x8c, 0x17, 0x31,
60 0xe1, 0x03, 0x28, 0x45, 0xb5, 0x82, 0x3d, 0xf9, 0xdb, 0x22, 0xf5, 0x03}; 60 0xe1, 0x03, 0x28, 0x45, 0xb5, 0x82, 0x3d, 0xf9, 0xdb, 0x22, 0xf5, 0x03};
61 const char asf_ext_stream_header[16] = {0xCB, 0xA5, 0xE6, 0x14, 61 const char asf_ext_stream_header[16] = {0xCB, 0xA5, 0xE6, 0x14,
62 0x72, 0xC6, 0x32, 0x43, 0x83, 0x99, 0xA9, 0x69, 0x52, 0x06, 0x5B, 0x5A}; 62 0x72, 0xC6, 0x32, 0x43, 0x83, 0x99, 0xA9, 0x69, 0x52, 0x06, 0x5B, 0x5A};
63 const char asf_metadata_header[16] = {0xea, 0xcb, 0xf8, 0xc5,
64 0xaf, 0x5b, 0x77, 0x48, 0x84, 0x67, 0xaa, 0x8c, 0x44, 0xfa, 0x4c, 0xca};
65
66 typedef struct {
67 // must be 0 for metadata record, might be non-zero for metadata lib record
68 uint16_t lang_list_index;
69 uint16_t stream_num;
70 uint16_t name_length;
71 uint16_t data_type;
72 uint32_t data_length;
73 uint16_t* name;
74 void* data;
75 } ASF_meta_record_t;
63 76
64 static char* get_ucs2str(const uint16_t* inbuf, uint16_t inlen) 77 static char* get_ucs2str(const uint16_t* inbuf, uint16_t inlen)
65 { 78 {
66 char* outbuf = calloc(inlen, 2); 79 char* outbuf = calloc(inlen, 2);
67 char* q; 80 char* q;
203 } 216 }
204 } 217 }
205 return 0; 218 return 0;
206 } 219 }
207 220
221 #define CHECKDEC(l, n) if (((l) -= (n)) < 0) return 0
222 static char* read_meta_record(ASF_meta_record_t* dest, char* buf,
223 int* buf_len)
224 {
225 CHECKDEC(*buf_len, 2 + 2 + 2 + 2 + 4);
226 dest->lang_list_index = LE_16(buf);
227 dest->stream_num = LE_16(&buf[2]);
228 dest->name_length = LE_16(&buf[4]);
229 dest->data_type = LE_16(&buf[6]);
230 dest->data_length = LE_32(&buf[8]);
231 buf += 2 + 2 + 2 + 2 + 4;
232 CHECKDEC(*buf_len, dest->name_length);
233 dest->name = (uint16_t*)buf;
234 buf += dest->name_length;
235 CHECKDEC(*buf_len, dest->data_length);
236 dest->data = buf;
237 buf += dest->data_length;
238 return buf;
239 }
240
241 static int get_meta(char *buf, int buf_len, int this_stream_num,
242 float* asp_ratio)
243 {
244 int pos = 0;
245 uint16_t records_count;
246 uint16_t x = 0, y = 0;
247
248 if ((pos = find_asf_guid(buf, asf_metadata_header, pos, buf_len)) < 0)
249 return 0;
250
251 CHECKDEC(buf_len, pos);
252 buf += pos;
253 CHECKDEC(buf_len, 2);
254 records_count = LE_16(buf);
255 buf += 2;
256
257 while (records_count--) {
258 ASF_meta_record_t record_entry;
259 char* name;
260
261 if (!(buf = read_meta_record(&record_entry, buf, &buf_len)))
262 return 0;
263 /* reserved, must be zero */
264 if (record_entry.lang_list_index)
265 continue;
266 /* match stream number: 0 to match all */
267 if (record_entry.stream_num && record_entry.stream_num != this_stream_num)
268 continue;
269 if (!(name = get_ucs2str(record_entry.name, record_entry.name_length))) {
270 mp_msg(MSGT_HEADER, MSGL_ERR, MSGTR_MemAllocFailed);
271 continue;
272 }
273 if (strcmp(name, "AspectRatioX") == 0)
274 x = LE_16(record_entry.data);
275 else if (strcmp(name, "AspectRatioY") == 0)
276 y = LE_16(record_entry.data);
277 free(name);
278 }
279 if (x && y) {
280 *asp_ratio = (float)x / (float)y;
281 return 1;
282 }
283 return 0;
284 }
285
208 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) 286 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)
209 { 287 {
210 uint8_t *buffer = *buf; 288 uint8_t *buffer = *buf;
211 int pos = *ppos; 289 int pos = *ppos;
212 290
334 break; 412 break;
335 } 413 }
336 case ASF_GUID_PREFIX_video_stream: { 414 case ASF_GUID_PREFIX_video_stream: {
337 sh_video_t* sh_video=new_sh_video(demuxer,streamh->stream_no & 0x7F); 415 sh_video_t* sh_video=new_sh_video(demuxer,streamh->stream_no & 0x7F);
338 unsigned int len=streamh->type_size-(4+4+1+2); 416 unsigned int len=streamh->type_size-(4+4+1+2);
417 float asp_ratio;
339 ++video_streams; 418 ++video_streams;
340 // sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize); 419 // sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize);
341 sh_video->bih=calloc((len<sizeof(BITMAPINFOHEADER))?sizeof(BITMAPINFOHEADER):len,1); 420 sh_video->bih=calloc((len<sizeof(BITMAPINFOHEADER))?sizeof(BITMAPINFOHEADER):len,1);
342 memcpy(sh_video->bih,&buffer[4+4+1+2],len); 421 memcpy(sh_video->bih,&buffer[4+4+1+2],len);
343 le2me_BITMAPINFOHEADER(sh_video->bih); 422 le2me_BITMAPINFOHEADER(sh_video->bih);
355 sh_video->fps=1.0f/sh_video->frametime; 434 sh_video->fps=1.0f/sh_video->frametime;
356 } else { 435 } else {
357 asf->avg_vid_frame_time=0.0; // only used for dvr-ms when > 0.0 436 asf->avg_vid_frame_time=0.0; // only used for dvr-ms when > 0.0
358 sh_video->fps=1000.0f; 437 sh_video->fps=1000.0f;
359 sh_video->frametime=0.001f; 438 sh_video->frametime=0.001f;
439 }
440 if (get_meta(hdr, hdr_len, streamh->stream_no, &asp_ratio)) {
441 sh_video->aspect = asp_ratio * sh_video->bih->biWidth /
442 sh_video->bih->biHeight;
360 } 443 }
361 444
362 if( mp_msg_test(MSGT_DEMUX,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V); 445 if( mp_msg_test(MSGT_DEMUX,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V);
363 //asf_video_id=streamh.stream_no & 0x7F; 446 //asf_video_id=streamh.stream_no & 0x7F;
364 //if(demuxer->video->id==-1) demuxer->video->id=streamh.stream_no & 0x7F; 447 //if(demuxer->video->id==-1) demuxer->video->id=streamh.stream_no & 0x7F;