[MPlayer-dev-eng] [PATCH] Support asf aspect ratio
Zuxy Meng
zuxy.meng at gmail.com
Sun Dec 3 14:58:28 CET 2006
Hi,
Attached patch reads and applies aspect ratio information in asf/wmv
files. Code follows the style of get_ext_stream_properties. A sample
file can be found at
http://download.microsoft.com/download/a/9/3/a9327df4-aeb5-46de-b438-d0f60da6fb54/Coral_Reef_Adventure_1080.exe
(It's a self-extracting cabinet file containing a wmv and can be
opened with 7-zip).
BTW: The patch currently only supports stream-wide aspect.
Packet-level aspect is, er, too complex and I haven't seen any sample
that really makes use of it!
--
Zuxy
Beauty is truth,
While truth is beauty.
PGP KeyID: E8555ED6
-------------- next part --------------
Index: libmpdemux/asf.h
===================================================================
--- libmpdemux/asf.h ???????? 21461??
+++ libmpdemux/asf.h ????????????
@@ -84,6 +84,20 @@
} ASF_content_description_t;
////////////////////////
+// ASF Metadata Record
+////////////////////////
+typedef struct __attribute__((packed)) {
+ // must be 0 for metadata record, might be non-zero for metadata lib record
+ uint16_t lang_list_index;
+ uint16_t stream_num;
+ uint16_t name_length;
+ uint16_t data_type;
+ uint32_t data_length;
+ uint16_t name[0];
+ // Followed by data
+} ASF_meta_record_t;
+
+////////////////////////
// ASF Segment Header
////////////////////////
typedef struct __attribute__((packed)) {
@@ -127,6 +141,17 @@
ASF_Authenticate_e
} ASF_StreamType_e;
+// Data types are usually represented by a uint16_t of following values
+typedef enum {
+ ASF_UCS16LEs_e, // Unicode string encoded as UCS16LE
+ ASF_Bytes_e, // Array of bytes
+ ASF_Bool_e, // BOOL represented by a uint32_t
+ ASF_DWORD_e,
+ ASF_QWORD_e,
+ ASF_WORD_e,
+ ASF_GUID_e
+} ASF_DataType_e;
+
typedef struct {
ASF_StreamType_e streaming_type;
int request;
@@ -174,6 +199,13 @@
(h)->comment_size = le2me_16((h)->comment_size); \
(h)->rating_size = le2me_16((h)->rating_size); \
}
+#define le2me_ASF_meta_record_t(h) { \
+ (h)->lang_list_index = le2me_16((h)->lang_list_index); \
+ (h)->stream_no = le2me_16((h)->stream_no); \
+ (h)->name_length = le2me_16((h)->name_length); \
+ (h)->data_type = le2me_16((h)->data_type); \
+ (h)->data_length = le2me_16((h)->data_length); \
+}
#define le2me_BITMAPINFOHEADER(h) { \
(h)->biSize = le2me_32((h)->biSize); \
(h)->biWidth = le2me_32((h)->biWidth); \
@@ -208,6 +240,7 @@
#define le2me_ASF_stream_header_t(h) /**/
#define le2me_ASF_file_header_t(h) /**/
#define le2me_ASF_content_description_t(h) /**/
+#define le2me_ASF_meta_record_t(h) /**/
#define le2me_BITMAPINFOHEADER(h) /**/
#define le2me_WAVEFORMATEX(h) /**/
#define le2me_ASF_stream_chunck_t(h) /**/
Index: libmpdemux/asfheader.c
===================================================================
--- libmpdemux/asfheader.c ???????? 21461??
+++ libmpdemux/asfheader.c ????????????
@@ -60,6 +60,8 @@
0xe1, 0x03, 0x28, 0x45, 0xb5, 0x82, 0x3d, 0xf9, 0xdb, 0x22, 0xf5, 0x03};
const char asf_ext_stream_header[16] = {0xCB, 0xA5, 0xE6, 0x14,
0x72, 0xC6, 0x32, 0x43, 0x83, 0x99, 0xA9, 0x69, 0x52, 0x06, 0x5B, 0x5A};
+const char asf_metadata_header[16] = {0xea, 0xcb, 0xf8, 0xc5,
+ 0xaf, 0x5b, 0x77, 0x48, 0x84, 0x67, 0xaa, 0x8c, 0x44, 0xfa, 0x4c, 0xca};
static char* get_ucs2str(const uint16_t* inbuf, uint16_t inlen)
{
@@ -205,6 +207,72 @@
return 0;
}
+static int get_meta(char *buf, int buf_len, int this_stream_num,
+ float* asp_ratio)
+{
+ int pos = 0;
+ uint64_t object_size;
+ uint16_t records_count, i;
+ uint32_t x = 0, y = 0;
+
+ if ((pos = find_asf_guid(buf, asf_metadata_header, pos, buf_len)) < 0)
+ return 0;
+
+ buf += pos;
+ object_size = *(uint64_t*)(buf - sizeof(uint64_t));
+ records_count = *(uint16_t*)buf;
+ buf += sizeof(uint16_t);
+
+ for (i = 0; i < records_count; i++) {
+ ASF_meta_record_t* record_entry = (ASF_meta_record_t*)buf;
+ uint32_t data;
+ uint16_t name_len;
+ char* name;
+
+ buf = (char*)&record_entry->name + record_entry->name_length +
+ record_entry->data_length;
+ le2me_ASF_meta_record_t(record_entry);
+ /* reserved, must be zero */
+ if (record_entry->lang_list_index)
+ continue;
+ /* match stream number: 0 to match all */
+ if (record_entry->stream_num && record_entry->stream_num != this_stream_num)
+ continue;
+ /* match name length */
+ if ((name_len = record_entry->name_length) !=
+ 2 * strlen("AspectRatioX") + 2)
+ continue;
+ if (!(name = get_ucs2str(record_entry->name, name_len))) {
+ mp_msg(MSGT_HEADER, MSGL_ERR, MSGTR_MemAllocFailed);
+ continue;
+ }
+ if (strncmp(name, "AspectRatio", strlen("AspectRatio")) == 0) {
+ char* pdata = (char*)record_entry->name + name_len;
+ switch (record_entry->data_type) {
+ case ASF_DWORD_e:
+ data = le2me_32(*(uint32_t*)pdata);
+ break;
+ case ASF_WORD_e:
+ data = le2me_16(*(uint16_t*)pdata);
+ break;
+ default:
+ free(name);
+ continue;
+ }
+ }
+ if (name[strlen("AspectRatio")] == 'X')
+ x = data;
+ else if (name[strlen("AspectRatio")] == 'Y')
+ y = data;
+ free(name);
+ if (x && y) {
+ *asp_ratio = (float)x / (float)y;
+ return 1;
+ }
+ }
+ return 0;
+}
+
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)
{
uint8_t *buffer = *buf;
@@ -336,6 +404,7 @@
case ASF_GUID_PREFIX_video_stream: {
sh_video_t* sh_video=new_sh_video(demuxer,streamh->stream_no & 0x7F);
unsigned int len=streamh->type_size-(4+4+1+2);
+ float asp_ratio;
++video_streams;
// sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize);
sh_video->bih=calloc((len<sizeof(BITMAPINFOHEADER))?sizeof(BITMAPINFOHEADER):len,1);
@@ -358,6 +427,10 @@
sh_video->fps=1000.0f;
sh_video->frametime=0.001f;
}
+ if (get_meta(hdr, hdr_len, streamh->stream_no, &asp_ratio)) {
+ sh_video->aspect = asp_ratio * sh_video->bih->biWidth /
+ sh_video->bih->biHeight;
+ }
if( mp_msg_test(MSGT_DEMUX,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V);
//asf_video_id=streamh.stream_no & 0x7F;
More information about the MPlayer-dev-eng
mailing list