📄 wma文件信息格式分析及代码 - mokemars的专栏 - csdnblog.htm
字号:
href="http://www.xianguo.com/subscribe.php?url=http://blog.csdn.net/mokemars/Rss.aspx"
target=_blank><IMG alt=订阅到鲜果
src="WMA文件信息格式分析及代码 - mokemars的专栏 - CSDNBlog.files/rss_xianguo.jpg"
border=0></A>
<DD><A
href="http://fusion.google.com/add?feedurl=http://blog.csdn.net/mokemars/Rss.aspx"
target=_blank><IMG alt=订阅到Google
src="WMA文件信息格式分析及代码 - mokemars的专栏 - CSDNBlog.files/rss_google.gif"
border=0></A>
<DD><A
href="http://www.zhuaxia.com/add_channel.php?url=http://blog.csdn.net/mokemars/Rss.aspx"
target=_blank><IMG alt=订阅到抓虾
src="WMA文件信息格式分析及代码 - mokemars的专栏 - CSDNBlog.files/rss_zhuaxia.gif"
border=0></A>
<DD><A
href="http://www.bloglines.com/sub/http://blog.csdn.net/mokemars/Rss.aspx"
target=_blank><IMG alt=订阅到BlogLines
src="WMA文件信息格式分析及代码 - mokemars的专栏 - CSDNBlog.files/rss_bloglines.gif"
border=0></A>
<DD><A
href="http://add.my.yahoo.com/rss?url=http://blog.csdn.net/mokemars/Rss.aspx"
target=_blank><IMG alt=订阅到Yahoo
src="WMA文件信息格式分析及代码 - mokemars的专栏 - CSDNBlog.files/rss_yahoo.gif"
border=0></A>
<DD><A
href="http://rss.gougou.com/find_rss.jsp?url=http://blog.csdn.net/mokemars/Rss.aspx"
target=_blank><IMG alt=订阅到GouGou
src="WMA文件信息格式分析及代码 - mokemars的专栏 - CSDNBlog.files/rss_gougou.gif"
border=0></A>
<DD><A
href="http://www.pageflakes.com/subscribe.aspx?url=http://blog.csdn.net/mokemars/Rss.aspx"
target=_blank><IMG alt=订阅到飞鸽
src="WMA文件信息格式分析及代码 - mokemars的专栏 - CSDNBlog.files/rss_pageflakes.gif"
border=0></A>
<DD><A
href="http://www.rojo.com/add-subscription?resource=http://blog.csdn.net/mokemars/Rss.aspx"
target=_blank><IMG alt=订阅到Rojo
src="WMA文件信息格式分析及代码 - mokemars的专栏 - CSDNBlog.files/rss_rojo.gif" border=0></A>
<DD><A
href="http://www.newsgator.com/ngs/subscriber/subfext.aspx?url=http://blog.csdn.net/mokemars/Rss.aspx"
target=_blank><IMG alt=订阅到newsgator
src="WMA文件信息格式分析及代码 - mokemars的专栏 - CSDNBlog.files/rss_newsgator.gif"
border=0></A>
<DD><A
href="http://www.netvibes.com/subscribe.php?url=http://blog.csdn.net/mokemars/Rss.aspx"
target=_blank><IMG alt=订阅到netvibes
src="WMA文件信息格式分析及代码 - mokemars的专栏 - CSDNBlog.files/rss_netvibes.gif"
border=0></A></SPAN> </DD></DL></DIV></DIV></DIV>
<DIV id=csdnblog_content>
<DIV class=gutter>
<DIV class=default_contents>
<DIV class=user_article>
<SCRIPT src="WMA文件信息格式分析及代码 - mokemars的专栏 - CSDNBlog.files/LoadFeedbackCount.js"
type=text/javascript></SCRIPT>
<H1><IMG height=16 alt=原创
src="WMA文件信息格式分析及代码 - mokemars的专栏 - CSDNBlog.files/authorship.gif" width=15
border=0> <A
href="http://blog.csdn.net/mokemars/archive/2008/03/20/2201064.aspx">WMA文件信息格式分析及代码</A><CITE
class=fav_csdnstylebykimi><A class=fav_csdnstylebykimi title=收藏到我的网摘中,并分享给我的朋友
href="javascript:d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(saveit=window.open('http://wz.csdn.net/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'saveit','scrollbars=no,width=590,height=300,left=75,top=20,status=no,resizable=yes'));saveit.focus();">收藏</A></CITE></H1>
<DIV class=blogstory><SPAN id=Post.ascx_ViewPost_PreviousAndNextEntriesUp>
<H3><A
href="http://blog.csdn.net/mokemars/archive/2008/03/20/2201083.aspx">新一篇: rtc在linux上的测试代码</A> | <A
href="http://blog.csdn.net/mokemars/archive/2006/09/26/1287943.aspx">旧一篇: WIN32
汇编写的加密解密软件</A></H3></SPAN>
<SCRIPT>function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</SCRIPT>
ASF文件和WMA文件格式差不多。具体请看下面我写的代码。文件分析根据mplayer其中的asfhead.c提供的代码进行分析。mplayer只解除出了标准的wma头信息,其扩展信息并没有解析出来。代码如下.<BR><BR><BR>/*<BR>每一个WMA文件,它的头16个字节是固定的,为十六进制的“30
26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE
6C”,用来标识这个是否为WMA文件。接下来的8个字节为一个整数,表示整个WMA文件头部的大小,这个头部里面包含了Tag信息等所有非音频信息,头部后面的是音频信息,我们在这里就不深入了解了。那个整数接下来的6个字节还没搞清楚是什么用的,不过不影响我们对Tag信息的读写。<BR><BR>
也就是说从文件开始偏移量为31开始,里面存放了很多帧,有我们需要的标准Tag信息,扩展Tag信息,WMA文件控制信息等等。每个帧不是等长的,但是帧头是固定的24个字节,其中前16字节是用来标识这个帧的名字,后8个字节是用来表示这个帧(包括帧头)的大小。这一点和MP3文件的ID3V2信息比较像。<BR><BR>
由于我们只需要读写Tag信息,而Tag信息又分别保存在两个帧里,分别为标准Tag帧和扩展Tag帧,所有我们只需要处理这两个帧,其他帧完全可以根据获得的帧长度来跳过。<BR><BR>
如图2,标准Tag帧只包含歌曲标题,艺术家,版权,备注四个内容。它的帧名是十六进制的“33 26 B2 75 8E 66 CF 11 A6 D9 00 AA
00 62 CE
6C”,在24个字节的帧头后紧跟着5个分别为2个字节的整数,前四个分别表示歌曲标题,艺术家,版权,备注的大小,第五个还不清楚是什么用的,大部分情况下是不使用的,即它的大小为0的。<BR><BR>
在这10个字节后,这四个信息的内容就按顺序存放了。记住,在WMA文件里,所有的文字都是按Unicode宽字符的编码方式储存的,而且每个字符串后面都又一个0结束字符的。<BR><BR>
再看扩展Tag帧,这里就比较麻烦了,里面包含的信息的个数是不确定的,每个信息也是按照像帧一样的方式组织起来的。扩展Tag帧的帧名是十六进制的“40 A4 D0
D2 07 E3 D2 11 97 F0 00 A0 C9 5E A8
50”,在24字节的帧头后先有一个两个字节的整数表示这个帧里一共有的扩展信息个数(ExNo)。<BR><BR>
每一个扩展信息包含扩展信息名字和对应的值。先有一个两个字节的整数来表示扩展名字信息的大小,接着是扩展信息,然后有一个两个字节的整数标志(Flag),这个后面再讲。然后又是一个两个字节的整数,表示值的大小。接着就是这个值。<BR><BR>
当扩展信息名字为WMFSDKVersion时,这个值表示的是这个WMA文件的版本;当扩展信息名字为WM/AlbumTitle时,这个值代表的就是专辑名;当扩展信息名字为WM/Genre时,这个值代表的就是流派;同理,很容易从扩展信息的名字看出这个值的用途的。这些扩展信息的名字和值几乎都是用Unicode的字符串来存储的,到现在为止只发现对下面两个情况例外<BR><BR>
下面再来看看那个标志Flag,这个基本上是为没什么用的(通常值为0),只对WM/TrackNumber和WM/Track这两个扩展信息名字有用,当Flag为3的时候后面的值(也就是曲目信息)是以4个字节的整数的形式表示,当Flag为0的时候,曲目信息是以普通的字符串形式表示的。<BR>*/<BR>#include
<stdio.h><BR>#include <stdlib.h><BR>#include
<string.h><BR>#include <unistd.h><BR>#include
<sys/types.h><BR>#include <sys/stat.h><BR>#include
<fcntl.h><BR>#include<sys/mman.h><BR>typedef unsigned long long
uint64_t;<BR>typedef unsigned long uint32_t;<BR>typedef unsigned short
uint16_t;<BR>typedef unsigned char uint8_t;<BR>typedef long long
int64_t;<BR>typedef short int16_t;<BR>typedef struct<BR>{<BR>
uint16_t title_size;<BR> uint16_t
author_size;<BR> uint16_t
copyright_size;<BR> uint16_t
comment_size;<BR> uint16_t
rating_size;<BR>}ASF_content_description_t;<BR>struct
asf_tags<BR>{<BR> char title[64];<BR> char
author[64];<BR> char copyright[64];<BR> char
comment[64];<BR> char rating[64];<BR> char
**ext_info;<BR>};<BR><BR>const uint8_t
ff_log2_tab[256]={<BR>
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,<BR>
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,<BR>
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,<BR>
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,<BR>
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,<BR>
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,<BR>
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,<BR>
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7<BR>};<BR>static
inline int av_log2(unsigned int v)<BR>{<BR> int
n;<BR><BR> n = 0;<BR> if (v &
0xffff0000) {<BR> v >>=
16;<BR> n += 16;<BR>
}<BR> if (v & 0xff00)
{<BR> v >>=
8;<BR> n += 8;<BR>
}<BR> n += ff_log2_tab[v];<BR><BR> return
n;<BR>}<BR>#define PUT_UTF8(val, tmp, PUT_BYTE)\<BR>
{\<BR> int bytes,
shift;\<BR> uint32_t in =
val;\<BR> if (in < 0x80)
{\<BR> tmp =
in;\<BR>
PUT_BYTE\<BR> } else
{\<BR> bytes =
(av_log2(in) + 4) /
5;\<BR> shift
= (bytes - 1) *
6;\<BR> tmp =
(256 - (256 >> bytes)) | (in >>
shift);\<BR>
PUT_BYTE\<BR>
while (shift >= 6)
{\<BR>
shift -=
6;\<BR>
tmp = 0x80 | ((in >> shift) &
0x3f);\<BR>
PUT_BYTE\<BR>
}\<BR> }\<BR>
}<BR><BR>const char asf_file_format_guid[16] = {0x30, 0x26, 0xB2, 0x75, 0x8E,
<BR> 0x66, 0xCF, 0x11, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE,
0x6C};/*ASF文件标志*/<BR><BR>const char asf_content_desc_guid[16] = {0x33, 0x26,
0xb2, 0x75,<BR> 0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00,
0x62, 0xce, 0x6c};/*ASF 标志信息*/<BR><BR>const char asf_stream_ext_desc_guid[16] =
{0x40, 0xA4, 0xD0, 0xD2, 0x07,<BR> 0xE3, 0xD2, 0x11, 0x97, 0xF0, 0x00,
0xA0, 0xC9, 0x5E, 0xA8, 0x50};/*ASF扩展标志信息*/<BR><BR><BR><BR>#define
AV_RL16(x) ((((uint8_t*)(x))[1] << 8) |
\<BR>
((uint8_t*)(x))[0])<BR>static char* get_ucs2str(const uint16_t* inbuf, uint16_t
inlen)<BR>{<BR> char* outbuf = calloc(inlen,
2);<BR> char* q;<BR> int
i;<BR> if (!outbuf)<BR>
{<BR> return NULL;<BR>
}<BR> q = outbuf;<BR> for (i = 0; i <
inlen / 2; i++)<BR> {<BR>
uint8_t tmp;<BR>
PUT_UTF8(AV_RL16(&inbuf[i]), tmp, *q++ = tmp;)<BR>
}<BR> return outbuf;<BR>}<BR>int find_asf_guid(char *buf,
const char *guid, int cur_pos, int buf_len)<BR>{<BR> int i;<BR> for
(i = cur_pos; i < buf_len - 19; i++) {<BR> if
(memcmp(&buf[i], guid, 16) == 0)<BR> return i
+ 16 + 8; // point after guid + length<BR> }<BR> return
-1;<BR>}<BR>int asf_ext_info_add(struct asf_tags* tags, const char *opt, const
char *param)<BR>{<BR> char **info =
tags->ext_info;<BR> int n = 0;<BR> for(n
= 0; info && info[2*n] != NULL; n++) <BR>
{<BR>
if(!strcasecmp(opt,info[2*n]))<BR>
{<BR>
free(info[2*n+1]);<BR>
info[2*n+1] = strdup(param);<BR>
return 0;<BR>
}<BR> }<BR> info = tags->ext_info =
(char**)realloc(info,(2*(n+2))*sizeof(char*));<BR> info[2*n] =
strdup(opt);<BR> info[2*n+1] =
strdup(param);<BR>
memset(&info[2*(n+1)],0,2*sizeof(char*));<BR> return
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -