`
mmdev
  • 浏览: 12933583 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

WMA文件信息格式分析及代码

 
阅读更多

WMA文件信息格式分析及代码 收藏
ASF文件和WMA文件格式差不多。具体请看下面我写的代码。文件分析根据mplayer其中的asfhead.c提供的代码进行分析。mplayer只解除出了标准的wma头信息,其扩展信息并没有解析出来。代码如下.


/*
每一个WMA文件,它的头16个字节是固定的,为十六进制的“30 26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE 6C”,用来标识这个是否为WMA文件。接下来的8个字节为一个整数,表示整个WMA文件头部的大小,这个头部里面包含了Tag信息等所有非音频信息,头部后面的是音频信息,我们在这里就不深入了解了。那个整数接下来的6个字节还没搞清楚是什么用的,不过不影响我们对Tag信息的读写。

也就是说从文件开始偏移量为31开始,里面存放了很多帧,有我们需要的标准Tag信息,扩展Tag信息,WMA文件控制信息等等。每个帧不是等长的,但是帧头是固定的24个字节,其中前16字节是用来标识这个帧的名字,后8个字节是用来表示这个帧(包括帧头)的大小。这一点和MP3文件的ID3V2信息比较像。

由于我们只需要读写Tag信息,而Tag信息又分别保存在两个帧里,分别为标准Tag帧和扩展Tag帧,所有我们只需要处理这两个帧,其他帧完全可以根据获得的帧长度来跳过。

如图2,标准Tag帧只包含歌曲标题,艺术家,版权,备注四个内容。它的帧名是十六进制的“33 26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE 6C”,在24个字节的帧头后紧跟着5个分别为2个字节的整数,前四个分别表示歌曲标题,艺术家,版权,备注的大小,第五个还不清楚是什么用的,大部分情况下是不使用的,即它的大小为0的。

在这10个字节后,这四个信息的内容就按顺序存放了。记住,在WMA文件里,所有的文字都是按Unicode宽字符的编码方式储存的,而且每个字符串后面都又一个0结束字符的。

再看扩展Tag帧,这里就比较麻烦了,里面包含的信息的个数是不确定的,每个信息也是按照像帧一样的方式组织起来的。扩展Tag帧的帧名是十六进制的“40 A4 D0 D2 07 E3 D2 11 97 F0 00 A0 C9 5E A8 50”,在24字节的帧头后先有一个两个字节的整数表示这个帧里一共有的扩展信息个数(ExNo)。

每一个扩展信息包含扩展信息名字和对应的值。先有一个两个字节的整数来表示扩展名字信息的大小,接着是扩展信息,然后有一个两个字节的整数标志(Flag),这个后面再讲。然后又是一个两个字节的整数,表示值的大小。接着就是这个值。

当扩展信息名字为WMFSDKVersion时,这个值表示的是这个WMA文件的版本;当扩展信息名字为WM/AlbumTitle时,这个值代表的就是专辑名;当扩展信息名字为WM/Genre时,这个值代表的就是流派;同理,很容易从扩展信息的名字看出这个值的用途的。这些扩展信息的名字和值几乎都是用Unicode的字符串来存储的,到现在为止只发现对下面两个情况例外

下面再来看看那个标志Flag,这个基本上是为没什么用的(通常值为0),只对WM/TrackNumber和WM/Track这两个扩展信息名字有用,当Flag为3的时候后面的值(也就是曲目信息)是以4个字节的整数的形式表示,当Flag为0的时候,曲目信息是以普通的字符串形式表示的。
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<sys/mman.h>
typedef unsigned long long uint64_t;
typedef unsigned long uint32_t;
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
typedef long long int64_t;
typedef short int16_t;
typedef struct
{
uint16_t title_size;
uint16_t author_size;
uint16_t copyright_size;
uint16_t comment_size;
uint16_t rating_size;
}ASF_content_description_t;
struct asf_tags
{
char title[64];
char author[64];
char copyright[64];
char comment[64];
char rating[64];
char **ext_info;
};

const uint8_t ff_log2_tab[256]={
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,
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,
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,
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,
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,
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,
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,
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
};
static inline int av_log2(unsigned int v)
{
int n;

n = 0;
if (v & 0xffff0000) {
v >>= 16;
n += 16;
}
if (v & 0xff00) {
v >>= 8;
n += 8;
}
n += ff_log2_tab[v];

return n;
}
#define PUT_UTF8(val, tmp, PUT_BYTE)/
{/
int bytes, shift;/
uint32_t in = val;/
if (in < 0x80) {/
tmp = in;/
PUT_BYTE/
} else {/
bytes = (av_log2(in) + 4) / 5;/
shift = (bytes - 1) * 6;/
tmp = (256 - (256 >> bytes)) | (in >> shift);/
PUT_BYTE/
while (shift >= 6) {/
shift -= 6;/
tmp = 0x80 | ((in >> shift) & 0x3f);/
PUT_BYTE/
}/
}/
}

const char asf_file_format_guid[16] = {0x30, 0x26, 0xB2, 0x75, 0x8E,
0x66, 0xCF, 0x11, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C};/*ASF文件标志*/

const char asf_content_desc_guid[16] = {0x33, 0x26, 0xb2, 0x75,
0x8e, 0x66, 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c};/*ASF 标志信息*/

const char asf_stream_ext_desc_guid[16] = {0x40, 0xA4, 0xD0, 0xD2, 0x07,
0xE3, 0xD2, 0x11, 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5E, 0xA8, 0x50};/*ASF扩展标志信息*/

#define AV_RL16(x) ((((uint8_t*)(x))[1] << 8) | /
((uint8_t*)(x))[0])
static char* get_ucs2str(const uint16_t* inbuf, uint16_t inlen)
{
char* outbuf = calloc(inlen, 2);
char* q;
int i;
if (!outbuf)
{
return NULL;
}
q = outbuf;
for (i = 0; i < inlen / 2; i++)
{
uint8_t tmp;
PUT_UTF8(AV_RL16(&inbuf[i]), tmp, *q++ = tmp;)
}
return outbuf;
}
int find_asf_guid(char *buf, const char *guid, int cur_pos, int buf_len)
{
int i;
for (i = cur_pos; i < buf_len - 19; i++) {
if (memcmp(&buf[i], guid, 16) == 0)
return i + 16 + 8; // point after guid + length
}
return -1;
}
int asf_ext_info_add(struct asf_tags* tags, const char *opt, const char *param)
{
char **info = tags->ext_info;
int n = 0;
for(n = 0; info && info[2*n] != NULL; n++)
{
if(!strcasecmp(opt,info[2*n]))
{
free(info[2*n+1]);
info[2*n+1] = strdup(param);
return 0;
}
}
info = tags->ext_info = (char**)realloc(info,(2*(n+2))*sizeof(char*));
info[2*n] = strdup(opt);
info[2*n+1] = strdup(param);
memset(&info[2*(n+1)],0,2*sizeof(char*));
return 1;
}
enum metadata_s
{
/* common info */
META_INFO_TITLE=0,
META_INFO_AUTHOR,
META_INFO_COPYRIGHT,
META_INFO_COMMENT,
META_INFO_WMFSDKVERSION,
META_INFO_WMFSDKNEEDED,
META_INFO_ISVBR,
META_INFO_WMPROMOTIONURL,
META_INFO_WMGENREID,
META_INFO_WMTRACK,
META_INFO_WMTRACENUMBER,
META_INFO_WMYEAR,
META_INFO_WMENCODINGTIME,
META_INFO_WMGENRE,
META_INFO_WMALBUMTITLE,
META_INFO_PEAKVALE,
META_INFO_AVERAGELEVEL
};
typedef enum metadata_s metadata_t;
static char *get_asf_info (struct asf_tags* tags,char *tag)
{
char **info = tags->ext_info;
int n;
if (!info || !tag)
return NULL;
for (n = 0; info[2*n] != NULL ; n++)
{
if (!strcmp (info[2*n], tag))
break;
}
return info[2*n+1] ? strdup (info[2*n+1]) : NULL;
}
char *get_metadata (struct asf_tags* tags,metadata_t type)
{
switch (type)
{
case META_INFO_TITLE:
{
return tags->title;
}
case META_INFO_AUTHOR:
{
return tags->author;
}
case META_INFO_COPYRIGHT:
{
return tags->copyright;
}
case META_INFO_COMMENT:
{
return tags->comment;
}
case META_INFO_WMFSDKVERSION:
{
return get_asf_info(tags,"WMFSDKVersion");
}
case META_INFO_WMFSDKNEEDED:
{
return get_asf_info(tags,"WMFSDKNeeded");
}
case META_INFO_ISVBR:
{
return get_asf_info(tags,"IsVBR");
}
case META_INFO_WMPROMOTIONURL:
{
return get_asf_info(tags,"WM/PromotionURL");
}
case META_INFO_WMGENREID:
{
return get_asf_info(tags,"WM/GenreID");
}
case META_INFO_WMTRACK:
{
return get_asf_info(tags,"WM/Track");
}
case META_INFO_WMTRACENUMBER:
{
return get_asf_info(tags,"WM/TrackNumber");
}
case META_INFO_WMYEAR:
{
return get_asf_info(tags,"WM/Year");
}
case META_INFO_WMENCODINGTIME:
{
return get_asf_info(tags,"WM/EncodingTime");
}
case META_INFO_WMGENRE:
{
return get_asf_info(tags,"WM/Genre");
}
case META_INFO_WMALBUMTITLE:
{
return get_asf_info(tags,"WM/AlbumTitle");
}
case META_INFO_PEAKVALE:
{
return get_asf_info(tags,"PeakValue");
}
case META_INFO_AVERAGELEVEL:
{
return get_asf_info(tags,"AverageLevel");
}
}
}
int read_asf_header(char *filename,struct asf_tags* tags)
{
int hdr_len;
char *hdr = NULL;
int pos;
int fd;
char buffer[16];
struct stat sb;
fd=open(filename,O_RDONLY);
if(fd==-1)
{
printf("open file error/n");
return 0;
}
memset(buffer,0,16);
fstat(fd,&sb); /*取得文件大小*/
hdr=mmap(NULL,sb.st_size,PROT_READ,MAP_PRIVATE,fd,0);
if(hdr== MAP_FAILED) /*判断是否映射成功*/
{
return 0;
close(fd);
}
strncpy(buffer,hdr,16);
if(strcmp(buffer,asf_file_format_guid))/*根据ASF标志信息判断是否为ASF文件*/
{
printf("file not an asf file/n");
close(fd);
munmap(hdr,sb.st_size);
return 0;
}
hdr_len=sb.st_size;
pos = find_asf_guid(hdr, asf_content_desc_guid, 0, hdr_len);/*找到标志信息位置*/
if (pos >= 0)
{
ASF_content_description_t *contenth = (ASF_content_description_t *)&hdr[pos];
unsigned char *string=NULL;
uint16_t* wstring = NULL;
uint16_t len;
pos += sizeof(ASF_content_description_t);
if (pos > hdr_len) goto len_err_out;
//le2me_ASF_content_description_t(contenth);
// extract the title
if((len = contenth->title_size) != 0)
{
wstring = (uint16_t*)&hdr[pos];
pos += len;
if (pos > hdr_len) goto len_err_out;
if ((string = get_ucs2str(wstring, len)))/*J解析成UTF8*/
{
strcpy(tags->title, string);
free(string);
}
}
// extract the author
if((len = contenth->author_size) != 0)
{
wstring = (uint16_t*)&hdr[pos];
pos += len;
if (pos > hdr_len) goto len_err_out;
if ((string = get_ucs2str(wstring, len)))
{
strcpy(tags->author, string);
free(string);
}
}
if((len = contenth->copyright_size) != 0)
{
wstring = (uint16_t*)&hdr[pos];
pos += len;
if (pos > hdr_len) goto len_err_out;
if ((string = get_ucs2str(wstring, len)))
{
strcpy(tags->copyright, string);
free(string);
}
}
// extract the comment
if((len = contenth->comment_size) != 0)
{
wstring = (uint16_t*)&hdr[pos];
pos += len;
if (pos > hdr_len) goto len_err_out;
if ((string = get_ucs2str(wstring, len)))
{
strcpy(tags->comment, string);
free(string);
}
}
// extract the rating
if((len = contenth->rating_size) != 0)
{
wstring = (uint16_t*)&hdr[pos];
pos += len;
if (pos > hdr_len) goto len_err_out;
if ((string = get_ucs2str(wstring, len)))
{
strcpy(tags->rating, string);
free(string);
}
}
}
pos = find_asf_guid(hdr, asf_stream_ext_desc_guid, 0, hdr_len);/*找到扩展信息标志位置*/
if (pos >= 0)
{
int i;
//unsigned char *ext_desc;
uint16_t flag;
uint16_t ext_desc_num;
unsigned char *string_name=NULL;
unsigned char *string_info=NULL;
uint16_t* wstring = NULL;
uint16_t len;
ext_desc_num=(*(uint16_t*)(&hdr[pos]));
//printf("%d/n",ext_desc_num);
pos += 2;
for(i=0;i<ext_desc_num;i++)
{
len=(*(uint16_t*)(&hdr[pos]));/*扩展名字信息大小*/
pos+=2;
wstring=(uint16_t*)&hdr[pos];
if ((string_name = get_ucs2str(wstring, len)))
{
//printf(" %d.扩展信息名字 %s/n", i,string_name);
//free(string_name);
}
pos+=len;
flag=(*(uint16_t*)(&hdr[pos]));/*标志*/
pos+=2;
len=(*(uint16_t*)(&hdr[pos]));/*扩展名字对应值大小*/
pos+=2;
wstring=(uint16_t*)&hdr[pos];
if ((string_info = get_ucs2str(wstring, len)))
{
//printf(" 扩展信息对应的值 %s/n",string_info);
//free(string_info);
}
asf_ext_info_add(tags,string_name,string_info);
pos+=len;
}
}
close(fd);
munmap(hdr,sb.st_size);
return 1;
len_err_out:
close(fd);
munmap(hdr,sb.st_size);
return 0;
}
int main(int argc,char **argv)
{
char *filename=argv[1];
int i;
char **info;
struct asf_tags tags;
tags.ext_info=(char**)malloc(2*sizeof(char*));
read_asf_header(filename,&tags);
char **ext_info;
printf("Title:%s/n",tags.title);
printf("Author:%s/n",tags.author);
printf("Copyright:%s/n",tags.copyright);
printf("Comment:%s/n",tags.comment);
printf("Rating:%s/n",tags.rating);
info = tags.ext_info;
for(i = 0; info[2*i] != NULL ; i++)
{
printf("%s: %s/n",info[2*i],info[2*i+1]);
}
return 0;
}
这里已经做了相关信息的接口,利于扩展开发。希望这些能对那些正在进行相关开发的人员提供一点帮助。本人从事音频视频解码,希望能和大家一起探讨,共通进步。联系方法QQ:263542344

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/benny5609/archive/2008/05/07/2409533.aspx

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yueyihua/archive/2010/04/20/5508286.aspx

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yueyihua/archive/2010/04/20/5508286.aspx

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yueyihua/archive/2010/04/20/5508286.aspx

分享到:
评论

相关推荐

    wma文件tag解析

    这个是用C#写的wma文件的标签解析代码,可以解析音轨,嵌入的歌词,和嵌入的图片等资源,是分析wma文件的很好的例子

    VC++ 解析mp3,wma文件

    这个是解析mp3,wma文件的c++代码,绝对使用,大家可以放心使用,已经经过很多测试的(环境vs2005)!

    wma 解码vc6.0 环境

    wma的解码器,完完全全的vc6.0的编译环境,是借助本站的wma unix系统下的一套代码和h264的vc6.0环境,自己读ffmpeg代码,写出来的wma的解码器。-

    解析用PHP读写音频文件信息的详解(支持WMA和MP3)

    php// AudioExif.class.php// 用PHP进行音频文件头部信息的读取与写入// 目前只支持 WMA 和 MP3 两种格式, 只支持常用的几个头部信息//// 写入信息支持: Title(名称), Artist(艺术家), Copyright(版权), Description...

    超强的音频格式文件处理动态库

    这个代码是一个支持不同音频格式的声音动态库文件,支持声音回放、音频编码、解码。他能解码(所以也能播放)WAV, MP3, OGG Vorbis, WMA, APE和CDA, 以及编码 WAV, MP3, OGG Vorbis, WMA和APE。在音频流回放上使用了...

    Java 音频Tag解码 源代码

    对 MP3 和 WMA 音乐文件的Tag解析源代码 支持ID3V1和ID3V2 MP3能够获取其中的歌词 解决乱码问题

    视频编码信息查看工具合集

    MediaInfo 用来分析视频和音频文件的编码和内容信息,是一款是自由软件 (免费使用、免费获得源代码,许可协议:GNU GPL/LGPL)。 MediaInfo可以获得多媒体文件的哪些信息? 内容信息:标题,作者,专辑名,音轨号,...

    视频音频编码分析软件MediaInfo0.7.7.6

    MediaInfo 用来分析视频和音频文件的编码和内容信息,是一款是自由软件 (免费使用、免费获得源代码,许可协议:GNU GPL/LGPL)。 MediaInfo可以获得多媒体文件的哪些信息? 内容信息:标题,作者,专辑名,音轨号,...

    音乐歌词LRC下载器(源代码)

    通过对千千静听包分析制作出来的歌词LRC下载,通过对MP3,WMA文件信息分析,自动下载歌词后与音乐名称相同并且位置在同一目录。方便一些MP3,MP4,手机的音乐歌词必须在同一目录且名称一样的要求。 可读取MP3 ID3V1 ID...

    视频编码信息查看工具_5款合集

    MediaInfo 用来分析视频和音频文件的编码和内容信息,是一款是自由软件 (免费使用、免费获得源代码,许可协议:GNU GPL/LGPL)。 MediaInfo可以获得多媒体文件的哪些信息? 内容信息:标题,作者,专辑名,音轨号,...

    音乐地址批量提取工具 v2.0 大客户版

    可提取mp3,rm,wmv,swf,mpga,mpg,wma,rmvb 等格式的影音文件。4.自动分析影音文件名称,如有必要可根据设定进行二级页面提取。5.适合建立局网内部的音乐搜索网站,提供asp搜索页面源代码。6.程序配置文件设定全面详细...

    从实例谈面向对象编程、工厂模式和重构

    我们可以把每种媒体文件类类型的相应信息放在配置文件中,然后根据配置文 件来选择创建具体的对象。并且,这种创建对象的方法将使用反射来完成。首先,创建配置文件: 程序代码 &lt;appSettings&gt; ...

    DotNetTextBox所见即所得编辑器控件 v3.3.1

    5) 默认的自动媒体文件格式增加SWF、WMA、FLV。 6) function文件夹增加flv.swf文件(FLV播放器核心文件)。 7) 更新了所有的多语言资源文件。 &lt;br&gt;2007/6/18 Version 3.1.1 beta &lt;br&gt;Updates: 1...

    流媒体基本知识及流媒体服务器搭建知识大全

    3.3.1 ASF高级串流格式简介以及和WMA/WMV的区别 49 3.3.2 ASF和WMA/WMV的区别官方解析 50 3.4 QuickTime容器(.mov) 50 3.5 Ogg vs Ogm容器(.ogg) 51 3.5.1 Ogg容器格式 51 3.5.2 Ogm 51 3.5.3 Ogg vs Ogm 52 3.6 ...

    商用版本文本编辑器DotNetTextBoxV6.0.8Source 源码

    11)修正及更新控件可视化配置工具(版本号1.0.2),增加了新版本中出现的新功能添加(代码清理及手动分页功能及修正生成上传配置文件中的错误)! 2008/5/20 Version 5.0.5 For VS2005/2008 Updates: 1)修正去掉代码...

    一款VB音频解码编码处理DLL动态库源代码

    WMA, APE和CDA等文件的编码与播放,为了更好的使用本类库,作者已将多个示例程序附在压缩包内,像音乐播放器实例 ,它使用本类库制作完成一个支持播放所有格式音频的播放器,支持显示3种可视化效果(频率、时间、...

    新版Android开发教程.rar

    也有分析认为,谷歌并不想做一个简单的手机终端制造商或者软件平台开发商,而意在一统传统互联网和 移 动互联网。----------------------------------- Android 编程基础 4 Android Android Android Android 手机新...

    新酷CMS网站管理系统 10.018.78.rar

    新酷內容管理系统具有强大的多级权限管理、针对不同信息的内容管理、全面细致的统计分析管理、简单便捷的标签和模板管理、接口丰富的数据管理、可自由定制的流程管理等功能。易于部署、操作简便、可扩展性强,解决了...

Global site tag (gtag.js) - Google Analytics