-
1. Mplayer 的事件机制
1) mplayer.c 事件使用
// 5.3) 处理暂停 PAUSE
while ((cmd = mp_input_get_cmd(20,1,1)) == NULL) {
if (sh_video && video_out && vo_config_count) video_out->check_events();
...
}
cmd = mp_input_get_cmd(0, 1, 0);
// 5.5) 键盘事件处理
while (!brk_cmd && (cmd = mp_input_get_cmd(0,0,0)) != NULL) {
switch (cmd->id) {
case MP_CMD_SEEK : {
...
}
}
}2) input/input.h 驱动程序
typedef int (*mp_key_func_t) (int fd);
typedef int (*mp_cmd_func_t) (int fd, char* dest, int size);
typedef void (*mp_close_func_t) (int fd);
extern void (*mp_input_key_cb) (int code); // Set this to grab all incoming key codes
typedef int (*mp_input_cmd_filter)(mp_cmd_t* cmd, int paused, void* ctx);int mp_input_add_cmd_fd (int fd, // The first arg is a file descriptor
int select, mp_cmd_func_t read_func, mp_close_func_t close_func);
void mp_input_rm_cmd_fd (int fd); // This removes driver, you usually don't need to use it
int mp_input_add_key_fd (int fd, // The args are the same as for the key's drivers.
int select, mp_key_func_t read_func, mp_close_func_t close_func);
void mp_input_rm_key_fd (int fd); // As for the cmd one you usually don't need this function.3) input/input.h 队列与命令操作
int mp_input_queue_cmd (mp_cmd_t* cmd); // 入队
mp_cmd_t* mp_input_get_queued_cmd (int peek_only); // 出队
mp_cmd_t* mp_input_get_cmd (int time, int paused, int peek_only);// 获取事件命令
mp_cmd_t* mp_input_parse_cmd (char* str); // 分析命令串
void mp_input_add_cmd_filter (mp_input_cmd_filter, void* ctx); // 增加命令过滤器
void mp_cmd_free (mp_cmd_t* cmd);
mp_cmd_t* mp_cmd_clone (mp_cmd_t* cmd);
void mp_input_init (void); // 事件处理初始化
void mp_input_uninit (void); // 事件处理关闭
int mp_input_check_interrupt(int time); //4) input/input.h 数据结构
- 命令类型
typedef struct mp_cmd {
int id; // 事件号码
char* name; // 事件名称
int nargs; // 事件参数个数
mp_cmd_arg_t args[MP_CMD_MAX_ARGS]; // 键盘事件变量数组
int pausing; // 暂停
} mp_cmd_t;如 { MP_CMD_LOADFILE, "loadfile", 1, { {MP_CMD_ARG_STRING, {0}}, {-1,{0}} } }
- 按键命名类型
typedef struct mp_key_name {
int key;
char* name;
} mp_key_name_t;如 { KEY_ENTER, "ENTER" }
KEY_ENTER 定义在 osdep/keycodes.h 文件中- 命令绑定表
typedef struct mp_cmd_bind {
int input[MP_MAX_KEY_DOWN+1];
char* cmd;
} mp_cmd_bind_t;如 { { MOUSE_BTN3, 0 }, "seek 10" }
5) input/input.c 事件队列
static mp_cmd_t* cmd_queue[CMD_QUEUE_SIZE]; // 队列缓冲
static unsigned int cmd_queue_length = 0, // 队列长度
cmd_queue_start = 0, // 队列头指针
cmd_queue_end = 0; // 队列尾指针队列操作:
int mp_input_queue_cmd(mp_cmd_t* cmd); // 入队
static mp_cmd_t* mp_input_get_queued_cmd(int peek_only) // 出队6) input/Makefile 事件模块库组成
SRCS=input.c joystick.c lirc.c
$(LIBNAME): $(OBJS)
$(AR) r $(LIBNAME) $(OBJS)
$(RANLIB) $(LIBNAME)
all: $(LIBNAME)7) 键盘配置文件 input.conf 的机制
input.c
/// 按键的名字表,用于 input.conf。如果你要加入一些新键, 你也需要在这里增加
static mp_key_name_t key_names[] = {...}2. Mplayer 的 GUI 处理
Makefile:
* ifeq ($(GUI),yes)
PARTS += Gui
endif
* ifeq ($(GUI),yes)
COMMON_DEPS += Gui/libgui.a
GUI_LIBS = Gui/libgui.a
endif
* Gui/libgui.a:
$(MAKE) -C Gui
* ifeq ($(GUI),yes)
-ln -sf $(PRG) $(BINDIR)/gmplayer
endif
* ifeq ($(GUI),yes)
@if test ! -d $(DATADIR)/Skin ; then mkdir -p $(DATADIR)/Skin ; fi
@echo "*** Download skin(s) at http://www.mplayerhq.hu/homepage/dload.html"
@echo "*** for GUI, and extract to $(DATADIR)/Skin/"
@if test ! -d $(prefix)/share/pixmaps ; then mkdir -p $(prefix)/share/pixmaps ; fi
$(INSTALL) -m 644 Gui/mplayer/pixmaps/mplayer-desktop.xpm
$(prefix)/share/pixmaps/mplayer-desktop.xpm
@if test ! -d $(prefix)/share/applications;then mkdir -p $(prefix)/share/applications; fi
$(INSTALL) -m 644 etc/mplayer.desktop $(prefix)/share/applications/mplayer.desktop
endifgui/mplayer/play.h
void mplEnd (void);
void mplFullScreen (void);
void mplPlay (void);
void mplPause (void);
void mplState (void);
void mplPrev (void);
void mplNext (void);
void mplCurr (void);void mplIncAudioBufDelay(void);
void mplDecAudioBufDelay(void);void mplRelSeek (float s);
void mplAbsSeek (float s);
float mplGetPosition (void);void mplPlayFork (void);
void mplSigHandler (int s);
void mplPlayerThread (void);void ChangeSkin (char* name);
void EventHandling (void);void mplSetFileName (char* dir, char* name, int type);
gui/mplayer/mplayer.h
void mplInit (void* disp);
void mplEventHandling (int msg, float param);void mplMainDraw (void);
void mplEventHandling (int msg, float param);
void mplMainMouseHandle(int Button, int X, int Y, int RX, int RY);
void mplMainKeyHandle (int KeyCode, int Type, int Key);
void mplDandDHandler (int num, char** files);void mplSubDraw (void);
void mplSubMouseHandle (int Button, int X, int Y, int RX, int RY);void mplMenuInit (void);
void mplHideMenu (int mx, int my, int w);
void mplShowMenu (int mx, int my);
void mplMenuMouseHandle(int X, int Y, int RX, int RY);void mplPBInit (void);
void mplPBShow (int x, int y);3. x86 Instruction Reference
Contents
1. Key to Operand Specifications
2. Key to Opcode Descriptions
2.1 Register Values
2.2 Condition Codes
2.3 SSE Condition Predicates
2.4 Status Flags
2.5 Effective Address Encoding: ModR/M and SIB
3. Key to Instruction Flags
4. x86 Instruction Set
4.1 AAA, AAS, AAM, AAD: ASCII Adjustments
...
4.337 XORPS: Bitwise Logical XOR of Single-Precision FP Values4. 基础性研究项目规划
确定公司至少未来两年视野的技术发展方向? -
1. 后处理 Postprocess 机制
config.h
/* Define this to enable MPEG 1/2 image postprocessing (requires a FAST CPU!) */
#define MPEG12_POSTPROC 1
/* Define this to enable image postprocessing in libavcodec (requires a FAST CPU!) */
#define FF_POSTPROCESS 1
/* Define to include support for OpenDivx postprocessing */
#undef HAVE_ODIVX_POSTPROCESS
libmpcodecs
Vd.c : // user wants postprocess but no pp filter yet:
postproc
软件缩放库 SWSLIB = libswscale.a
libmpcodecs
Vd_libmpeg2.c : #ifdef MPEG12_POSTPROC
libavcodec
Makefile : $(SWSLIB) $(PPLIB) $(SPPLIB)
Imgconvert.c : integrate deinterlacing, postprocessing and scaling in the conversion process
libavcodec/libpostproc
postprocess.c
gui/mplayer/gtk
Opts.c : static GtkWidget * CBPostprocess;
libmpdvdkit2
Ioctl.c : p_ssc->SRB_PostProc = hEvent;
Ioctl.h : unsigned long *SRB_PostProc;
loader/dshow
Interfaces.h : HRESULT STDCALL (*get_PPLevel)(IDivxFilterInterface* This, int* PPLevel);
// current postprocessing level2. {standard input}: Assembler messages:
static inline int FMUL32(int x, int y) {
int lo, hi;
asm volatile(
"imull %3\n\t"
"shld edx, eax," AV_TOSTRING(32-FIX_Q) // SHLD dest,src,count
"\n\t" // shifts "dest" to the left "count" times and the
// bit positions opened are filled with the most
// significant bits of "src".
: "=a" (lo), "=d" (hi)
: "%a" (x), "rm" (y)
: "cc"
);
return (hi);
}{standard input}:459: Error: too many memory references for `shld'
Answer: AT&T assembler
shld edx, eax, 16 => shld 16, %eax, %edx3. ChangeLog on MPlayer (1.0) pre8: June 11, 2006
工作点: DOCS: Drivers: Decoders: Demuxers: Streaming: FFmpeg/libavcodec:
GUI: Filters: MEncoder: Ports: Others: -
1. Mplayer 的生成机制
1) libdha 的代码是谁生成的?
pci_dev_ids.c, pci_ids.h 等;2) config.mak 文件是谁生成并复制到几个目录下的?
libao2/config.mak:
include ../config.mak
OPTIONAL_SRCS = ao_win32.c
OPTIONAL_OBJS = ao_win32.o
libaf, libvo2. 领导风格
我们在这里运用二维分析法来看企业领导风格,指挥性行为和支持性行为, 这两种行为的不同组合会得出四
种不同的领导方式。 任何一位领导者都不可能仅仅只有其中的一种行为, 总是或多或少地存在着其他的行
为,所以指挥性行为、支持性行为在每一个领导者的身上都或多或少地存在,只是程度上有所不同而已。 有
的人指挥性行为偏强,有的人支持性行为偏强。 把指挥性行为作为一条横轴,支持性行为作为一条纵轴,通
过这样两个轴就会得出四个部分的内容,也就是四种不同的领导风格和方法, 即命令型风格、教练型风格、
支持型风格和放任型风格。 -
1. 自动 configure 脚本 conf_josa.sh
#! /bin/shcat << EOF
Mplayer configure for MinGW/FC5/ARM automation tool.
Copyright reights reserved. josa version. Yuchun Ji, 2006.06.06EOF
CFLAGS="--disable-mencoder"
case "josa_$1" in
josa_arm) echo 'This is for ARM';
CFLAGS="$CFLAGS --prefix=/usr/local/arm/3.2/arm-linux --datadir=/tmp"
CFLAGS="$CFLAGS --cc=arm-linux-gcc --host-cc=gcc --target=arm-armv4l-linux"
CFLAGS="$CFLAGS --disable-rtc --disable-dvdread --disable-live"
CFLAGS="$CFLAGS --disable-win32 --disable-mpdvdkit"
CFLAGS="$CFLAGS --disable-tv-v4l2 --disable-tv-v4l --disable-tv"
CFLAGS="$CFLAGS --disable-inet6 --disable-gethostbyname2 --disable-vstream"
CFLAGS="$CFLAGS --disable-iconv --disable-langinfo --disable-vm"
CFLAGS="$CFLAGS --disable-xf86keysym --disable-edl --disable-cdparanoia"
CFLAGS="$CFLAGS --disable-freetype --disable-fontconfig --disable-unrarlib"
CFLAGS="$CFLAGS --disable-enca --disable-macosx --disable-sighandler"
CFLAGS="$CFLAGS --enable-static --enable-fbdev --disable-sdl --disable-x11"
CFLAGS="$CFLAGS --with-extralibdir=/usr/local/arm/3.2/arm-linux/lib"
CFLAGS="$CFLAGS --with-extraincdir=/usr/local/arm/3.2/arm-linux/include"
./configure $CFLAGS;;
josa_mingw) echo 'this is for MinGW';
CFLAGS="$CFLAGS --enable-runtime-cpudetection --enable-static"
./configure $CFLAGS;;
josa_fc5) echo 'This is for FC5';
CFLAGS="$CFLAGS --cc=gcc32"
./configure $CFLAGS;;
josa_) echo 'This is for auto';
./configure $CFLAGS;;
*) cat << EOFUsage: $0 [OPTIONS]...
arm - for ARM
fc5 - for FC5
mingw - for MinGW
$CFLAGS
EOFesac
-
Leo: IBM吞并了Rational的东西, 里面有类似的自动化测试工具,MI(可能是MT)是世界上最大的软件自动测
试软件公司。Jee: 那里讲的是 automated unit testing 测试工具自动化问题。这篇文章与此有关系,但还不是一回事。
这里要解决的问题出测试系统外,还有分析生疏系统的模型分析与工作原理分析。Jee: 负载统计与系统是否崩溃是他们要做的,但这里只是一个实例。
Leo: 差不多,那些东西一般也能看代码各个部分对CPU的占用情况
Leo: http://www.parasoft.com/jsp/products/home.jsp?product=CppTest
http://cunit.sourceforge.netJee: 给点资源?
Leo: 以前(10年前)这种系统少,所以做一个很容易挣钱,现在美国好多大公司都在搞,包括Mi 和IBM,做起
来就难了。Jee: 哈哈,关键是需求!
Leo: 是啊,灵活性可定时手工编写的代码好。自动构造的代码限制比较多。
Leo: 以前有个美国人作了个类似的系统,挣了几百万美金。
Jee: 不错的注意,但实际跟踪总是有太多的灵活性需求。
Leo: mplayer虽然也可以记录一写跟踪信息,但对性能的测试没有josa详细。该文件的方法与计划很好,但需
要手工编写代码,如果再加上编译技术,就可以对任何代码进行自动跟踪了。Jee: 空缺谈不上,Mplayer 当然不需要这些东西,但并不代表它们没有类似的东西。另该文重在分析方法探讨。
Leo: 该系统填补了Mplayer的一个空缺。如果以后能有一个工具,可以自动把josa系统的函数加入待检测的
代码中,然后统计形成数据库,进而给出图形化报告。那就可以形成一个产品了。多让我难为情,老子好象讲过“甘为人同”,我没做到,太显眼了。
Lee:
> 老Jee,
> 逐行读完了你的大作,很是激动和兴奋 - 我们的队伍中有人能为提升我们对技术的认识水平,那是多么幸
> 运啊!
>
> 也许不用这些方法,或干脆不具备这样的思路,我们同样可以制作出产品。 但是,要想设计出好的产品,
> 没有你这种对方法和理论孜孜以求的态度,肯定是办不到的。 建议将你的这篇论文(这是爱兰数码的第一
> 篇学术论文),用交流培训的方式在研发工程师中进行学习。不仅学习“系统跟踪分析”,还要学习你的“学
> 习、思考、总结”的良好习惯和方式。 -
1. 浮点操作分析
目前看,IMDCT 和 FFT 两个文件的浮点运算都已转化完毕,因此只剩下 wmadec.c 文件,集中精力分析它是
当前的主要工作。首先扫描所有的浮点运算并加以简单的注释和分析。2. Tremor MDCT 分析 asm_arm.h 文件
static inline ogg_int32_t MULT32(ogg_int32_t x, ogg_int32_t y) {
int lo,hi;
asm volatile("smull\t%0, %1, %2, %3" : "=&r"(lo),"=&r"(hi) : "%r"(x),"r"(y) : "cc");
return(hi);
}#define MB() asm volatile ("" : : : "memory")
static inline ogg_int32_t MULT31(ogg_int32_t x, ogg_int32_t y) {
return MULT32(x,y)<<1;
}static inline void XPROD31(ogg_int32_t a, ogg_int32_t b, ogg_int32_t t, ogg_int32_t v,
ogg_int32_t *x, ogg_int32_t *y)
{
int x1, y1, l;
asm( "smull %0, %1, %4, %6\n\t"
"smlal %0, %1, %5, %7\n\t"
"rsb %3, %4, #0\n\t"
"smull %0, %2, %5, %6\n\t"
"smlal %0, %2, %3, %7"
: "=&r" (l), "=&r" (x1), "=&r" (y1), "=r" (a)
: "3" (a), "r" (b), "r" (t), "r" (v)
: "cc" );
*x = x1 << 1;
MB();
*y = y1 << 1;
}static inline void XNPROD31(ogg_int32_t a, ogg_int32_t b, ogg_int32_t t, ogg_int32_t v,
ogg_int32_t *x, ogg_int32_t *y)
{
int x1, y1, l;
asm( "rsb %2, %4, #0\n\t"
"smull %0, %1, %3, %5\n\t"
"smlal %0, %1, %2, %6\n\t"
"smull %0, %2, %4, %5\n\t"
"smlal %0, %2, %3, %6"
: "=&r" (l), "=&r" (x1), "=&r" (y1)
: "r" (a), "r" (b), "r" (t), "r" (v)
: "cc" );
*x = x1 << 1;
MB();
*y = y1 << 1;
}3. Tremor MDCT 分析 mdct.c 文件
// 逆向修正离散余弦变换 IMDCT
// 只用到 XPROD31 复数乘法 和 蝶形操作 mdct_butterflies 和 mdct_bitreverse 位倒换三操作
#include "misc.h"
#include "mdct_lookup.h"void mdct_backward(int n, DATA_TYPE *in, DATA_TYPE *out) {
XPROD31( iX[4], iX[6], T[0], T[1], &oX[2], &oX[3] );
XNPROD31( iX[6], iX[4], T[0], T[1], &oX[0], &oX[1] );
mdct_butterflies(out+n2, n2, shift) {
mdct_butterfly_generic(x+(points>>i)*j, points>>i, 4<<(i+shift));
mdct_butterfly_32(x+j);
};
mdct_bitreverse( out, n, step, shift) {
DATA_TYPE r3 = bitrev12(bit++);
XPROD32( r0, r1, T[1], T[0], &r2, &r3 );
};
}4. Tremor MDCT 分析—头文件
misc.h
#include "asm_arm.h"
mdct.h
#define DATA_TYPE ogg_int32_t
os_types.h
typedef int32_t ogg_int32_t;
inttypes.h
typedef long int32_t;5. sincos 查找表 tremor/mdct_lookup.h 文件
#include "os_types.h"/* {sin(2*i*PI/4096), cos(2*i*PI/4096)}, with i = 0 to 512 */
static LOOKUP_T sincos_lookup0[1026] = {
X(0x00000000), X(0x7fffffff), X(0x003243f5), X(0x7ffff621),
X(0x006487e3), X(0x7fffd886), X(0x0096cbc1), X(0x7fffa72c),
X(0x00c90f88), X(0x7fff6216), X(0x00fb5330), X(0x7fff0943),
X(0x012d96b1), X(0x7ffe9cb2), X(0x015fda03), X(0x7ffe1c65),
X(0x01921d20), X(0x7ffd885a), X(0x01c45ffe), X(0x7ffce093),
...
}6. 数据类型 ogg_int* 与 X 转化 tremor/os_types.h 文件
#ifdef _LOW_ACCURACY_
# define X(n) (((((n)>>22)+1)>>1) - ((((n)>>22)+1)>>9))
# define LOOKUP_T const unsigned char
#else
# define X(n) (n)
# define LOOKUP_T const ogg_int32_t
#endif#include <inttypes.h>
typedef int64_t ogg_int64_t;
typedef int32_t ogg_int32_t;
typedef uint32_t ogg_uint32_t;
typedef int16_t ogg_int16_t;7. 用 Python 进行双定点精度测量实验
a = 3.45678
b = 0.54321
c = a * b预测:大数用小精度,小数用高精度,可能效果最好。
如何验证?两种取舍方法:取整、四舍五入 rintf = round ? int
--------------------------------------------------
三种精度设定:小、均、大
qa1 = 1<<7 qa2 = 1<<8 qa3 = 1<<9
qb1 = 1<<9 ab2 = 1<<8 ab3 = 1<<7
---------------- -------------- ----------------
fa = rintf(a*qa)
fb = rintf(b*qb)
fc = fa * fb
nc = fc / float(qa*qb)8. 代码编辑器新特性
- 两个文件间的行绑定
- 块定义、块隐蔽、块展开、块关闭、块锁定9. Miscs
Themselve
This program will print its self! I guess its not of any real use, but I think its clever.
main(a) {a="main(a) {a=%c%s%c;printf(a,34,a,34);}";printf(a,34,a,34);} -
1. 批处理编译文件 josamake
#! /bin/shcd libavcodec
make
cd ../libmpcodec
make
cd ..
make
cp mplayer.exe /winux/AVStuff2. 关于微软的 WMA9DMO 无损压缩音频格式
WMA9DMO-LWS.wma
Windows Media Audio 9 Lossless
VBR Quality 100, 44 kHz, 2 channel 16 bit 1-pass VBR
Requested audio codec family [wma9dmo] (afm=dmo) not available.
Enable it at compilation.
03:273. 数据结构 ao_functions_s, 在文件 audio_out.h 中定义:
typedef struct ao_functions_s { // 面向 mplayer 的接口
...
int (*play)(void* data, int len, int flags);
} ao_functions_t;4. 设备选定 mplayer.c/main()
// 4.4) 设置音频 SETUP AUDIO
audio_out = init_best_audio_out(audio_driver_list, 0, // 插件标记 plugin flag
force_srate ? force_srate : ao_data.samplerate,
audio_output_channels ? audio_output_channels : ao_data.channels,
audio_output_format ? audio_output_format : ao_data.format, 0)));
mp_msg(MSGT_CPLAYER, MSGL_INFO, "AO: [%s] %dHz %dch %s (%d bps)\n",
audio_out->info->short_name,
ao_data.samplerate, ao_data.channels,
af_fmt2str_short(ao_data.format),
af_fmt2bits(ao_data.format)/8);5. 播放调用 mplayer.c/main()
// 5.1.1) 初始化
playsize = audio_out->get_space();
// 5.1.4) 播放音频 play audio:
playsize = audio_out->play(sh_audio->a_out_buffer, playsize, 0);6. 音频设备接口,在 audio_out_internal.h 文件中
接口原形头文件中原语 (play...) 和元语 (LIBAO_EXTERN(win32)) 定义:
static int play(void* data,int len,int flags);
#define LIBAO_EXTERN(x) ao_functions_t audio_out_##x =\
{ &info, control, init, uninit, reset,
get_space, play, get_delay,\
audio_pause, audio_resume\
}7. win32 音频设备定义 ao_win32.c 文件
1) 设备定义
static ao_info_t info = { // 设备信息
"Windows waveOut audio output",
"win32",
"Sascha Sommer <saschasommer@freenet.de>",
""
};
LIBAO_EXTERN(win32) // 最终的 win32 音频设备名为 audio_out_win322) play 包装处理
// plays 'len' bytes of 'data', it should round it down to outburst*n
// return: number of bytes played
static int play(void* data,int len,int flags) {
len = (len/ao_data.outburst)*ao_data.outburst;
return write_waveOutBuffer(data,len);
}8. 音频设备列表及选择 audio_out.c
ao_functions_t* audio_out_drivers[] = {
&audio_out_mpegpes,
#ifdef HAVE_DXR2
&audio_out_dxr2,
#endif
#ifdef HAVE_DIRECTX
&audio_out_dsound,
#endif
#ifdef HAVE_WIN32WAVEOUT
&audio_out_win32,
#endif
...
&audio_out_null,
// should not be auto-selected:
&audio_out_pcm,
NULL
};音频设备选择:
ao_functions_t* init_best_audio_out(char** ao_list, int use_plugin,
int rate, int channels, int format, int flags)9. win32 音频输出的最终处理 ao_win32.c 文件
1) 音频输出函数 write_waveOutBuffer()
// writes data into buffer, based on ringbuffer code in ao_sdl.c
static int write_waveOutBuffer(unsigned char* data, int len) {
WAVEHDR* current;
int len2 = 0;
int x;
while (len>0) {
current = &waveBlocks[buf_write];
if (buffered_bytes==BUFFER_COUNT*BUFFER_SIZE) break;
// unprepare the header if it is prepared
if (current->dwFlags & WHDR_PREPARED)
waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR));
x = BUFFER_SIZE-buf_write_pos;
if (x>len) x=len;
memcpy(current->lpData+buf_write_pos,data+len2,x);
if (buf_write_pos==0) full_buffers++;
len2+=x; len-=x;
buffered_bytes+=x; buf_write_pos+=x;
//prepare header and write data to device
current->dwBufferLength = buf_write_pos;
waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR));
waveOutWrite(hWaveOut, current, sizeof(WAVEHDR));if (buf_write_pos>=BUFFER_SIZE) { // buffer is full find next
// block is full, find next!
buf_write=(buf_write+1)%BUFFER_COUNT;
buf_write_pos=0;
}
}
return len2;
}2) 全局变量
static WAVEHDR* waveBlocks; // pointer to our ringbuffer memory
static HWAVEOUT hWaveOut; // handle to the waveout device3) Windows 本地函数库
#include <mmsystem.h>
MMRESULT WINAPI waveOutWrite(HWAVEOUT,LPWAVEHDR,UINT);这些函数是 MinGW 系统自身所拥有的, 可在 mingw/inlcude 和 lib 目录下找到头文件 mmsystem.h 和
库文件 libwinmm.a。因此当喇叭不响时,可在此拦截看是否正确的数据到达这里。
10.尺寸为 64 的蝶形傅立叶变换算法的反转表 revtab,FFI_R:64:
0: 0 32 16 48 8 40 24 56 4 36 20 52 12 44 28 60
16: 2 34 18 50 10 42 26 58 6 38 22 54 14 46 30 62
32: 1 33 17 49 9 41 25 57 5 37 21 53 13 45 29 61
48: 3 35 19 51 11 43 27 59 7 39 23 55 15 47 31 63 -
1. 重要的 Bug 发现
文件 libavcodec/fft.c/ff_fft_init() 函数中:
s->exptab[i].re = FF2N(c1); // 要否浮点转定点
s->exptab[i].im = FN2F(s1);
将第二行改为:
s->exptab[i].im = FF2N(s1);2. 予旋转 pre rotation 出错 bug
复数乘法 CNUL 定义:
#define FMUL(a,b) (((a)*(b))>>FIX_Q)
#ifdef JOSA_FIXPOINT
#define MUL16(a,b) FMUL(a,b)
#else
#define MUL16(a,b) ((a)*(b))
#endif
#define CMUL(pre, pim, are, aim, bre, bim) \
{\
pre = (MUL16(are, bre) - MUL16(aim, bim));\
pim = (MUL16(are, bim) + MUL16(bre, aim));\
}予旋转调用:
in1 = input; // 予旋转 pre rotation
in2 = input + n2 - 1;
for (k=0; k<n4; k++) {
j = revtab[k];
CMUL(z[j].re, z[j].im, *in2, *in1, tcos[k], tsin[k]);
in1 += 2;
in2 -= 2;
}MDCT 的 tcos/tsin 表:
FMI_C:1024:
0: -0.99998 -0.99998 -0.99998 -0.99998 -0.99997 -0.99995 -0.99995 -0.99994 -0.99991 -0.99989
FMI_S:1024:
0: -0.00018 -0.00172 -0.00325 -0.00479 -0.00632 -0.00786 -0.00938 -0.01093 -0.01245 -0.01399倒位表 revtab: FFI_R:1024:
0: 0 1 0 0 65534 0 402 0 65531 0 804 0 65524 0 1206输入数据 IMC_I:1024:
0: -5.12188 -0.09649 -0.09649 -0.09649 0.30554 0.30554 0.10453 0.00402 0.00261 ...
1008: ... 0.00127 0.00127 0.00127 0.00127 0.00127 0.00127 0.00127 0.00127 0.00127演算公式:
z[0].im = (MUL16(are, bim) + MUL16(bre, aim)) = (MUL16(in2, ts0) + MUL16(tc0, in1))
= 0.00127 * -0.00018 + -0.99998 * -5.12188 = 5.12178, 按照浮点数算正确
= 83 * -12 + -65535 * -335668 = -996 + 21998002380
= -1 + 335662 = 335661 = 5.12178, 按照定点数算也正确
表面看来,定点、浮点都正确,但是 21998002380 > 2147483648(2^31) 造成整数溢出。输出数据 FFC_I:2048: 错误 Q16
0: -0.02051 0.12177 0.00000 -0.00180 -0.01761 -0.00868 0.01761 -0.00867 -0.01888 -0.00549输出数据 FFC_I:2048: 正确 QN
0: -0.02056 5.12188 0.00000 -0.00180 -0.01760 -0.00867 0.01760 -0.00866 -0.01887 -0.00549 -
1. 音视频输出设备 ao/vo 全局变量,在 mplayer.c 中定义。
// 公共“先进先出” FIFO 函数, 和键盘/事件(keyboard/event) FIFO 码
#include "fifo.c"
int noconsolecontrols = 0;
vo_functions_t *video_out = NULL;
ao_functions_t *audio_out = NULL;
int fixed_vo = 0;
int eof = 0;2. 音频输出设备 audio_out
typedef struct ao_functions_s { // 面向 mplayer 的接口
ao_info_t *info;
int (*control) (int cmd,void *arg);
int (*init) (int rate,int channels,int format,int flags);
void (*uninit) (int immed);
void (*reset) ();
int (*get_space) ();
int (*play) (void* data,int len,int flags);
float (*get_delay) ();
void (*pause) ();
void (*resume) ();
} ao_functions_t;3. 视频输出设备 video_out
typedef struct vo_functions_s {
vo_info_t *info;
uint32_t (*preinit) (const char *arg);
uint32_t (*config) (uint32_t width, uint32_t height,uint32_t d_width,uint32_t d_height,
uint32_t fullscreen, char *title, uint32_t format);
uint32_t (*control) (uint32_t request, void *data, ...);
uint32_t (*draw_frame) (uint8_t *src[]);
uint32_t (*draw_slice) (uint8_t *src[], int stride[], int w,int h, int x,int y);
void (*draw_osd) (void);
void (*flip_page) (void);
void (*check_events) (void);
void (*uninit) (void);
} vo_functions_t;4. 设备的使用
1) 根据参数指定或自动选择最恰当的输出设备;
2) 予初始化设备;
3) 初始化配置设备;
4) 使用输出设备;
音频:
视频:video_out->check_events();
video_out->flip_page();
video_out->control(VOCTRL_DUPLICATE_FRAME, NULL);
5) 释放关联资源,关闭设备; -
1. 键盘事件数据结构 mp_cmd_t 定义
事件命令变量类型 mp_cmd_arg_t
typedef struct mp_cmd_arg {
int type;
mp_cmd_arg_value_t v;
} mp_cmd_arg_t;typedef struct mp_cmd {
int id; // 事件号码
char* name; // 事件名称
int nargs; // 事件参数个数
mp_cmd_arg_t args[MP_CMD_MAX_ARGS]; // 键盘事件变量数组
int pausing; // 暂停
} mp_cmd_t;2. 键盘事件定义在 input/input.c 文件中,如下列出:
static mp_cmd_t mp_cmds[] = {
{MP_CMD_SEEK, "seek", 1, { {MP_CMD_ARG_FLOAT,{0}}, {MP_CMD_ARG_INT,{0}}, {-1,{0}}}},
#ifdef USE_EDL
{MP_CMD_EDL_MARK, "edl_mark", 0, { {-1,{0}} } },
#endif
{MP_CMD_AUDIO_DELAY, "audio_delay", 1, { {MP_CMD_ARG_FLOAT,{0}}, {-1,{0}} } },
{MP_CMD_SPEED_INCR, "speed_incr", 1, { {MP_CMD_ARG_FLOAT,{0}}, {-1,{0}} } },
{MP_CMD_SPEED_MULT, "speed_mult", 1, { {MP_CMD_ARG_FLOAT,{0}}, {-1,{0}} } },
{MP_CMD_SPEED_SET, "speed_set", 1, { {MP_CMD_ARG_FLOAT,{0}}, {-1,{0}} } },
{MP_CMD_QUIT, "quit", 0, { {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
{MP_CMD_PAUSE, "pause", 0, { {-1,{0}} } },
...
{MP_CMD_GET_VO_FULLSCREEN, "get_vo_fullscreen", 0, { {-1,{0}} } },
{MP_CMD_GET_SUB_VISIBILITY,"get_sub_visibility", 0, { {-1,{0}} } },
{0, NULL, 0, {} }
}; -
1. av_log 跟踪扩展
1) 原始跟踪机制回顾
跟踪元语 #define tprintf(...) av_log(NULL, AV_LOG_DEBUG, __VA_ARGS__)
调试元语 #define dprintf(fmt,...) av_log(NULL, AV_LOG_DEBUG, fmt, __VA_ARGS__)基础跟踪函数适配栈:av_log -> av_vlog -> av_log_callback -> av_log_default_callback
2) Josa 扩展 Jyc Open-Source Analysis
在 libavcodec/utils.c 中增加:
static FILE *josaf;
static void josa(...) { // 仿照 av_log_default_callack 重写 josa
fprintf(f, "...", ...);
}void av_log_file_open(char *fn){// 初始化 Josa
josaf = fopen(fn, "wt");
fprintf(josaf, "Josa Begin!\n");
av_log_callback = josa; // 用 josa 替换缺省的 av_log_default_callback
}
void av_log_file_close() { // 关闭 Josa
fprintf(josaf, "Josa End!\n");
fclose(josaf);
}在 avcodec.h 中增加 av_log_file_open(..) 和 av_log_file_close() 函数的声明
extern void av_log_file_open(char *fn);
extern void av_log_file_close() ;3) Josa 使用
主程序 mplayer 中初始化和关闭前的操作:
av_log_file_open("josa.log.txt");
tprintf("***decode_block: %d:%d\n", wdc->frame_count - 1, wdc->block_num);
av_log_file_close();4) TRACE 控制
#ifdef DEBUG // loader/config.h
#define TRACE printf
#endif
#ifdef TRACE // wmadec.c
tprintf("*...");
#endif增加如下语句作为欲调试模块 mplayer.c, wmadec.c, mdct.c 的第一条语句即可,此为静态方法。 其实
本来可以作为编译配置的选项,可能应是--enable-debug 吧,但有时我们不想作为 debug 编译,因此可
能是个缺陷。
#define TRACE 1 // 人工设定跟踪 2006.05.15 By Yuchun Ji5) Enable debug 编译选项
./configure --enable-debug
But failed, error is: "No space left on device"
Answer: Really no space in F:\, prompt is D:\..., prompt error.2. wmadec.c 再进一步
1) 调用关系图:
wma_decode_superframe() // 解码超帧
wma_decode_frame() // 解码帧
wma_decode_block() // 解码块
av_log2() //
decode_exp_lsp() // 解码指数 lsp
get_bits() //
get_bits_trace() //
av_log() //
wma_lsp_to_curve() //
pow_m1_4() //
decode_exp_vlc() // 解码指数变长编码 vlc2) MDCT 的使用
wma_decode_init(AVCodecContext * avctx)
ff_mdct_init
wma_decode_block(WMADecodeContext *wdc)
ff_imdct_calc(&wdc->mdct_ctx[bsize], output, wdc->coefs[ch], wdc->mdct_tmp);这些 mdct 函数定义在 libavcodec/mdct.c 中。且都是基于 FFT 的,如在 ff_mdct_calc 中会调用 FFT
的 ff_fft_calc(&s->fft, x) 函数等。3) WMA 块解码流程
// 1) 计算当前块的长度
// 2) 现在检查块长度和帧长度是否一致
// 3) 如果没有频道编码, 没必要继续下去。
// 4) 读取总增益(gain)并提取相应的转义码系数位数
// 5) 计算系数数量
// 6) 复合编码
// 7) exposant 在短块上可被插值
// 8) 分析频谱系数: 只是 RLE 编码
// 9) 规格化 normalize?
// 10) 最终计算 MDCT 系数
// 11) 跟踪处理
// 12) 中边立体声处理
// 13) 建立窗: 我们确保当窗重叠时,他们的平方和永远为 1。(MDCT 重构规则) XXX: 和输出连接起来
// 14) 声道处理
// 15) 下个块3. Debug mplayer
./configure --enable-runtime-cpudetection --enable-static
./configure --enable-static, Error: unable to find a register to spill in class `FLOAT_REGS'
1) gcc -march=architecture-type
>Number: 7798
>Category: target
>Synopsis: unable to find a register to spill in class `FLOAT_REGS'
>Description: gcc fails to compile a floating point function, complaining that is "unable
to find a register to spill in class `FLOAT_REGS'"
>How to repeat:
typedef struct { float x, y; } Vector;
int circle_intersect(Vector m, int r, Vector pos, Vector v, Vector *t1, Vector *t2) {
Vector delta = { pos.x - m.x, pos.y - m.y };
float delta_v = delta.x * v.x + delta.y * v.y;
float dis = delta_v * delta_v + r * r - ( delta.x * delta.x + delta.y * delta.y );
float t;
if ( dis < 0 ) return 0;
dis = sqrt( dis );
t = -delta_v + dis;
t1->x = pos.x + t * v.x; t1->y = pos.y + t * v.y;
t = -delta_v - dis;
t2->x = pos.x + t * v.x; t2->y = pos.y + t * v.y;
return 1;
}
2) First time I've seen this kind of error... I tried with 3.1 with the
same options and I got:
cb_search.c:500: Internal compiler error in ...
It looks to me like a compiler bug that's only triggered when -march=pentium4 is turned on.
3) Skip over it! -
1. MSYS Developer Tool Kit, Version 1.0.1, http://www.mingw.org/msys.shtml
What is msysDTK?
----------------
I created msysDTK to provide the MinGW developer with tools that aren't easily portable to the
native Win32. My desire will be to provide methods within MSYS that will allow these tools to
one day be moved to the mingwDTK. That will happen when I'm able to build a “native” version
of autoconf using MSYS and ActivePerl. It is named msysDTK because the binaries are dependent
on the msys-1.0.dll.What does msysDTK contain?
--------------------------
The tools I've provided with msysDTK the following list of tools: autoconf, automake, libtool,
autogen, guile, cvs, openssl, openssh, inetutil and perl. I've also included the /usr/share/vim
directory for the already included /bin/vim binary. NOTE: I've only included the client tool of
any package providing both server and client. It is not my goal for MSYS to provide server
services. The cvs, openssl, openssh and inetutils are provided for remote operations with
SourceForge. Perl is provided because autoconf, automake and libtool require it. Guile is
provided because autogen requires it. And autogen is provided, just because it's a nice tool.Where are the man and info files?
---------------------------------
I've not provided these as they are readily obtainable via the web. If you really want them,
grab the source files for each package and build them yourself or download the info versions
from the web.2. Mplayer, libao2\.depend file analysis:
audio_out.o: audio_out.c ../config.h audio_out.h ../mp_msg.h ../config.h \
../help_mp.h ../help/help_mp-en.h ../mplayer.h ../libvo/sub.h \
../subreader.h ../subreader.h
ao_mpegpes.o: ao_mpegpes.c ../config.h audio_out.h audio_out_internal.h ...
ao_null.o: ao_null.c ../config.h ../libaf/af_format.h audio_out.h ...
ao_pcm.o: ao_pcm.c ../config.h ../bswap.h ../subopt-helper.h ...
ao_sdl.o: ao_sdl.c ../config.h ../mp_msg.h ../config.h ../help_mp.h ...
ao_oss.o: ao_oss.c ../config.h ../mp_msg.h ../config.h ../mixer.h ...
ao_arts.o: ao_arts.c /usr/include/kde/artsc/artsc.h ...
ao_esd.o: ao_esd.c ../config.h audio_out.h audio_out_internal.h ...
ao_alsa.o: ao_alsa.c ../config.h ../subopt-helper.h ../mixer.h ...3. Mplayer decoder meeting
Float-point process performance list
No.Name Description Speed
-- ----- ------------------------- -----
1) FPA Hardware FP Acceleration 1
2) FPE FP Emulation 100
3) FPLib FP Library, 25
4) F2FP Float-point to Fix-point 1
-- ----- ------------------------- ----- -
1. Install FC5 from hard disk
grub> kernel (hd0,6)/FC5i386/vmlinuz
grub> initrd (hd0,6)/FC5i386/initrd.img
grub> boot2. Grub4dos, menu.lst as follows:
title Fedora Core 5
root (hd0,5)
kernel /vmlinuz-2.6.15-1.2054_FC5 ro root=LABEL=/ vga=0x317
initrd /initrd-2.6.15-1.2054_FC5.img3. Install vfat file system /mnt/winux
mkdir /mnt/winux
mount -t vfat -o iocharset=utf8,umask=000 /dev/hda7 /mnt/winux4. Install
cross-arm-gcc
gcc3.25. Rebuild mplayer
mplayer -
1. MPlayer 项目的国际化多语言 i18n 安排
1) 目录 help 中放置着多语言的字符串资源头文件,其中 help_mp-zh_CN.h 是中文字符串资源头文件:
// Translated by Lu Ran <hephooey@fastmail.fm>
// Synced with help_mp-en.h 1.121
// ========================= MPlayer help ===========================
……
#define MSGTR_NoGui "MPlayer没有编译GUI的支持!\n"
#define MSGTR_GuiNeedsX "MPlayer GUI需要X11!\n"
#define MSGTR_Playing "播放 %s.\n"2) 项目文件 Makefile,使用 config.mak 中定义的语言 HELP_FILE
help_mp.h: help/help_mp-en.h $(HELP_FILE)
@echo '// WARNING! This is a generated file. Do NOT edit.' > help_mp.h
@echo '// See the help/ subdir for the editable files.' >> help_mp.h
ifeq ($(CHARSET),)
@echo '#include "$(HELP_FILE)"' >> help_mp.h
else
iconv -f `cat $(HELP_FILE).charset` -t $(CHARSET) "$(HELP_FILE)" >> help_mp.h
endififneq ($(HELP_FILE),help/help_mp-en.h)
@echo "Adding untranslated messages to help_mp.h"
@echo '// untranslated messages from the English master file:' >> help_mp.h
@help/help_diff.sh $(HELP_FILE) < help/help_mp-en.h >> help_mp.h
endif3) 生成的编译配置文件 config.mak, 定义语言 HELP_FILE
HELP_FILE = help/help_mp-en.h4) 国际字符集支持的编译配置
--enable-i18n 打开国际字符集支持 _experimental_ gnu gettext() support [autodetect]
--charset 转化帮助信息到该字符集5) 可能的问题:
目前语言选择是由开发者在编译配置时完成的,能否在编译完成后,即在运行时由用户设置语言?2. VMWare start X Window Server
Install
1) Configure Virtual CD-ROM to image of VMWare\linux.iso
2) Start VMWare to FC4
3) Change /etc/inittab, change mode 5->3
4) Mount CD-ROM for FC4
mount -t iso9660 /dev/cdrom /media/cdrom
5) Install VMWare tools from CD-ROM
cd /media/cdrom/...
vmware-install.pl
Change the X11 screen size to 800x600, others press return.
6) startsx
7) view the X11 configuration file
/etc/X11/xorg.conf3. 关于研究性项目的工作程序
1) 研究性项目建议阶段
《研究性项目调查表》
2) 技术委员会汇总研究性项目,作出基本评判
列出《研究性项目建议清单》
初步制定出《基础性研究项目规划》
3) 报请公司层面评审
参与部门:董事长、总经理、市场部、研发部
评议、修改通过《基础性研究项目规划》
评审确定正式立项的《研究性项目立项清单》
4) 交由项目管理中心组织实施
基本采用一般性工程项目的项目管理办法
5) 研究性项目总结评审
评审、备案各个《研究性项目总结报告》
建立各个研究性项目的应用效果的跟踪评价4. Miscs
cumulative 累积的
take from the table 重新讨论
Obstacle 障碍 -
1. 有关 Benchmark 基准测试
1) 基准测试 benchmark 用的全局变量:
double video_time_usage = 0;
double vout_time_usage = 0;
static double audio_time_usage = 0;
static int total_time_usage_start = 0;
static int total_frame_cnt = 0;
static int drop_frame_cnt = 0; // 丢掉的帧总数
int benchmark = 0;
2) 基准测试选项
{"benchmark", &benchmark, CONF_TYPE_FLAG, 0, 0, 1, NULL},
3) 全局变量 benchmark 的使用
- 在主程序 mplayer.c 的 main() 函数中
if (benchmark) {
double tot = video_time_usage + vout_time_usage + audio_time_usage;
double total_time_usage;
total_time_usage_start = GetTimer() - total_time_usage_start;
total_time_usage = (float)total_time_usage_start*0.000001;
mp_msg(MSGT_CPLAYER, MSGL_INFO,
"\nBENCHMARKs: VC:%8.3fs VO:%8.3fs A:%8.3fs Sys:%8.3fs = %8.3fs\n",
video_time_usage, vout_time_usage, audio_time_usage,
total_time_usage-tot, total_time_usage);
……
}
- 其它使用的地方 liba52/resample_mmx.c
/* 优化 TODO/NOTES: movntq 稍微快一点(0.5% 用当前的 test.c 基准程序),但那只是在test.c中,
* 因此需要在实际情况下测试,那就意味着在 C / MMX2 / MMX / 3DNOW 的版本中。*/
4) 编译选项以及运行命令行中的 benchmark 选项说明
mplayer dvd://1 -nosound -vo null -benchmark
使用 -benchmark 使得 MPlayer 尽可能地快速播放电影,但还是根据你硬件的不同, 可能需要一会儿。
每次 demux_mpg 报告一个帧率的变更。2. 有关配置与选项
1) 可配置选项的数据结构 m-option.h
typedef struct m_option {
char *name; // 选项名称
void *p; // 指针
m_option_type_t* type; // 选项类型
unsigned int flags; // 标记
double min, max; // 最大最小值
// 这通常是个函数指针,to hold a 'reverse to defaults' func.
// 名义上它可传递任意类型的扩展变量
// Passing a 'default func' is still valid for all func based option types
void* priv; // 私有指针,类型依赖数据,用于所有类型的扩展设置
} m_option_t;
2) 选项类型定义 m-option.h
typedef struct m_option_type m_option_type_t;
struct m_option_type {
char* name; // 类型名称
char* comments; // 类型说明,语法描述,等
unsigned int size; // 存储所需的尺寸
unsigned int flags; // 标记// 分析 parse 是唯一的必须函数,其它的都可为空 NULL
// If dst if non-NULL it should create/update the save slot
// If dst is NULL it should just test the validity of the arg if possible
// Src tell from where come this setting (ie cfg file, command line, playlist, ....
// It should return 1 if param was used, 0 if not.
// On error it must return 1 of the error code below
int (*parse)(m_option_t* opt, char *name, char *param, void* dst, int src);
// 以人可阅读的形式打印该类型的值 Print back a value in human form
char* (*print)(m_option_t* opt, void* val);// These 3 will be a memcpy in 50% of the case, it's called to save/restore the status of
// the var it's there for complex type like CONF_TYPE_FUNC*
// update a save slot (dst) from the current value in the prog (src)
void (*save)(m_option_t* opt, void* dst, void* src);
// set the current value (dst) from a save slot
void (*set)(m_option_t* opt, void* dst, void* src);
// 在两个数值槽(slot)间复制(if NULL and size > 0 a memcpy will be used)
void (*copy)(m_option_t* opt, void* dst, void* src);
// 释放为存储一个该类型槽而分配的数据空间
void (*free)(void* dst);
};
3) 整数配置类型 m_option_type_int,m-option.c
m_option_type_t m_option_type_int = {
"Integer", "Int number", // 类型名和描述
sizeof(int), 0, // 尺寸,标记
parse_int, print_int, // 分析整数,输出整数
copy_opt, copy_opt, // 即 save/set 方法
NULL, NULL // 无 copy/free 方法
};
4) 配置类型列表
// FIXME: 向后兼容
#define CONF_TYPE_FLAG (&m_option_type_flag)
#define CONF_TYPE_INT (&m_option_type_int)
#define CONF_TYPE_FLOAT (&m_option_type_float)
#define CONF_TYPE_DOUBLE (&m_option_type_double)
#define CONF_TYPE_STRING (&m_option_type_string)
#define CONF_TYPE_FUNC (&m_option_type_func)
#define CONF_TYPE_FUNC_PARAM (&m_option_type_func_param)
#define CONF_TYPE_PRINT (&m_option_type_print)
#define CONF_TYPE_PRINT_INDIRECT (&m_option_type_print_indirect)
#define CONF_TYPE_FUNC_FULL (&m_option_type_func_full)
#define CONF_TYPE_SUBCONFIG (&m_option_type_subconfig)
#define CONF_TYPE_STRING_LIST (&m_option_type_string_list)
#define CONF_TYPE_POSITION (&m_option_type_position)
#define CONF_TYPE_IMGFMT (&m_option_type_imgfmt)
#define CONF_TYPE_AFMT (&m_option_type_afmt)
#define CONF_TYPE_SPAN (&m_option_type_span)
#define CONF_TYPE_OBJ_SETTINGS_LIST (&m_option_type_obj_settings_list)
#define CONF_TYPE_OBJ_PRESETS (&m_option_type_obj_presets)
#define CONF_TYPE_CUSTOM_URL (&m_option_type_custom_url)
#define CONF_TYPE_OBJ_PARAMS (&m_option_type_obj_params)
5) 使用 cfg-mplayer.h
m_option_t mplayer_opts[] = {
/* name, pointer, type, flags, min, max */
{"vo", &video_driver_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL},
{"benchmark", &benchmark, CONF_TYPE_FLAG, 0, 0, 1, NULL},
#ifdef HAVE_XINERAMA
{"xineramascreen", &xinerama_screen, CONF_TYPE_INT, CONF_RANGE, 0, 32, NULL},
#endif
……
}3. 运行配置文件 mplayer/mplayer/config 示例分析
vo=directx
double=yes
font=F:\WINDOWS\Fonts\arial.ttf # 使用 windows 自身的 ttf 字体文件失败
autosync=100
framedrop=yes # 允许丢帧
quiet=yes
#adapter=2
#fs=yes错误:F:\WINDOWS\Fonts\arial.ttf doesn't look like a font description, ignoring.
Cannot load font: F:\WINDOWS\Fonts\arial.ttf4. Mplayer 支持的字幕(sub)格式
MPlayer 可以显示和电影文件伴随的字幕格式。当前支持以下字幕格式:
- VOBsub // .sub 文件
- OGM
- CC (closed caption)
- MicroDVD
- SubRip
- SubViewer
- Sami
- VPlayer
- RT
- SSA
- PJS (Phoenix Japanimation Society)
- MPsub // MPlaye 自身的格式
- AQTitle
- JACOsubMPlayer 还可将以上格式的字幕文件转化为(除前三项)如下目标格式, 后跟命令选项:
- MPsub: -dumpmpsub
- SubRip: -dumpsrtsub
- MicroDVD: -dumpmicrodvdsub
- JACOsub: -dumpjacosub
- Sami: -dumpsami5. Miscs
PAC Perceptual Audio Coding 音频感知编码
VQ Vector Quantization 矢量量化
IIR Infinite Impulse Response 无限脉冲响应
FIR Finite Impulse Response 有限脉冲响应
FLAC Free Lossless Audio Codec
ATH Absolute Threshold of Hearing
ARM Advanced RISC Machine 高级精简指令集机器
SPL Sound pressure level 声压
Nom 名义上 -
1. 日志 av_log 系统分析
1) 理解 tprintf, bitstream.h
跟踪(TRACE)格式化输出
定义:#define tprintf(...) av_log(NULL, AV_LOG_DEBUG, __VA_ARGS__)
使用:tprintf("\n");2) 理解 dprintf, common.h
调试(DEBUG)格式化输出
定义:#define dprintf(fmt,...) av_log(NULL, AV_LOG_DEBUG, fmt, __VA_ARGS__)
使用:dprintf("flags1=0x%x flags2=0x%x\n", flags1, flags2);3) 公共格式化输出函数 av_log 定义机制 utils.c
- AV 格式化记录函数 av_log 定义
void av_log(void* avcl, int level, const char *fmt, ...) {
va_list vl;
va_start(vl, fmt);
av_vlog(avcl, level, fmt, vl);
va_end(vl);
}
- AV 虚拟记录函数 av_vlog 定义
void av_vlog(void* avcl, int level, const char *fmt, va_list vl) {
av_log_callback(avcl, level, fmt, vl);
}
- AV 记录回调函数 ac_log_callback 全局变量声明
static void (*av_log_callback)(void*,int, const char*, va_list) = av_log_default_callback;
- AV 缺省记录回调函数 av_log_default_callback 定义
static void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl) {
static int print_prefix=1;
AVClass* avc= ptr ? *(AVClass**)ptr : NULL; // 此处用到 AVClass 类
if (level>av_log_level) return; // 如果登记等级大于需登记的等级设定,则返回
#undef fprintf // 暂时屏蔽预定义文件格式化输出函数fprintf
if (print_prefix && avc) fprintf(stderr, "[%s @ %p]", avc->item_name(ptr), avc);
#define fprintf please_use_av_log // 暂时屏蔽真实文件格式化输出函数fprintf
print_prefix = strstr(fmt, "\n") != NULL;
vfprintf(stderr, fmt, vl);
}4) 记录等级 av_log_level 定义(avcodec.h)
#define AV_LOG_QUIET -1 // 安静模式
#define AV_LOG_ERROR 0 // 出错
#define AV_LOG_INFO 1 // 信息
#define AV_LOG_DEBUG 2 // 警告2. Miscs
Lyric file, LRC file format
Enhanced LRC files playback (word synchronised files)
Time tag text file.
Install putty.exe
AST : Autoumatic Scan Tracking 自动扫描跟踪
dumb 哑的、没声音
Doxygen generated C project.
http://mplayerhq.hu/~michael/ffmpeg-doxy/wmadec_8c.html
机会成本 opportunity cost 为了得到某种东西所必须放弃的东西。 -
1. Utils.c 中平方根与对数表
const uint8_t ff_sqrt_tab[128] = {
0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 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,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11
}; // 验证 for i in range(128) : print int(sqrt(i))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
}; // 验证:for i in range(256) : print int(log(i, 2))2. 即求 v 的指数函数 av_log2(v)
文件 Common.h 中定义
static inline int av_log2(unsigned int v) { // 求 v 的以 2 为底的对数,即求 v 的指数部分
int n = 0;
if (v & 0xffff0000) { v >>= 16; n += 16; }
if (v & 0xff00) { v >>= 8; n += 8; }
n += ff_log2_tab[v];
return n;
}3. Sorenson 3 (SVQ3)
Which is included in the FFmpeg/libavcodec package.
Sorenson is a video codec developed by Sorenson Media and licensed to Apple who distribute it
with their QuickTime Player. We are currently able to decode all version of Sorenson video
files with the following decoders:
- Sorenson Video v1 (fourcc SVQ1) - decoding supported by native codec (libavcodec)
- Sorenson Video v3 (fourcc SVQ3) - decoding supported by native codec (libavcodec)4. MPlayer components
FFmpeg/libavcodec
FFmpeg contains an open source codec package, which is capable of decoding streams with
various audio and video codecs. It also offers an impressing encoding facility and higher
speed than the Win32 codecs or the DivX.com DivX4/5 libraries!libmad is a multiplatform, integer (internally 24bit PCM) only MPEG audio decoding library. It
does not handle broken files well, and it sometimes has problems with seeking, but it may
perform better on FPU-less (such as ARM) platform than mp3lib.5. Audio codecs
The most important audio codecs above all:- MPEG layer 1/2/3 (MP1/2/3) audio (native code, with MMX/SSE/3DNow! optimization)
- Windows Media Audio 7 and 8 (AKA WMAv1 and WMAv2) (native code, with libavcodec)
- Windows Media Audio 9 (WMAv3) (using DMO DLL)
- AC3 Dolby audio (native code, with MMX/SSE/3DNow! optimization)
- AC3 passing through sound card hardware
- AAC
- Ogg Vorbis audio codec (native library)
- RealAudio: DNET (low bitrate AC3), Cook, Sipro and ATRAC3
- QuickTime: Qualcomm and QDesign audio codecs
- VIVO audio (g723, Vivo Siren)
- Voxware audio (using DirectShow DLL)
- alaw and ulaw, various gsm, adpcm and pcm formats and other simple old audio codecs -
1. 什么是 VQF?
众所周知,MP3是目前世界上最流行的音频格式之一。她的优点就在于:第一,压缩率较高的同时,音质仍能
接近于CD;第二,它是完全免费的。 但是,现在有一种新的音乐格式正悄然兴起,并且她的压缩技术已经相
当成熟,她就是最有希望打破MP3在网络音乐领域霸主地位的VQF。VQF即TwinVQ(Transform-domain Weighted Interleave Vector Quantization 简称 TwinVQ),是由 Nippon
Telegraph and Telephone(NTT) 同YAMAHA公司开发的一种音频压缩技术,经过不少权威评测,认为这是一种
绝对优于MPEG Layer III(MP3)的技术。在音频压缩率和音质上,VQF比起Mp3都有很大的优势。由于采用了TwinVQ音频压缩技术,VQF的音频压缩率比标准的MPEG音频压缩率高出近一倍,可以达到1:18左右
甚至更高。而像Mp3、RA这些广为流行的压缩格式一般只有1:12左右。因此,在音频压缩率方面,MP3 和RA都
败在 VQF 手上。这么高的压缩率是否会对音质有影响呢?回答是“丝毫不会有任何影响。“当VQF 以 44KHz
-80kbit/s的音频采样率压缩音乐时,它的音质优于44KHz-128kbit/s的MP3,当VQF以44KHz-96kbit/s 的频率
压缩时,它的音质几乎等于 44KHz-256kbit/s的MP3!说了那么多的理论数据,还是让我们对VQF有一个感性
认识吧!压缩过MP3的朋友想必都知道,压缩一首4:30的歌曲,大约需要4250KB的硬盘空间。而同一首歌曲,
如果使用VQF音频压缩技术的话,那只需要2650KB左右的硬盘空间。或许你会不相信,但这的确是事实。如果你想多了解关于VQF的信息,可以去访问http://www.vqf.com
不过VQF还有其它优点和缺点的,虽然网站和杂志上没有说明,只是我在使用的一点经验。VQF 在制作的过程
中,要比MP3慢很多,因为压缩比比 MP3大,所需要的时间也就教长,不过这方面的缺点只是针对制作人了。
还有一个不是缺点的优点,就是VQF在制作的时候,制作软件会自动检测MP3或是CD的音质是否达到128kbit,
如果不能达到,它将不执行文件转换,对我来说就比较头疼了,但对乐迷来说,你所下载的VQF格式音质绝对
出色,如果MP3的话96kbit的网上可是一大吧。 VQF文件在播放的过程中解码所耗费的CPU的资源要大于MP3,
如果你听到播放某个VQF格式的歌曲的时候出现象受干扰一样“兹兹”响的效果,就是资源不足所造成的,如
果要消除这种效果,你先把多余程序关闭,然后把VQF播放器关闭,然后再打开,就正常了。最重要的一点,我采用VQF格式作为网站音乐格式的原因是因为MP3经常被禁止,采用VQF可以暂时替代一下。
在这之前有很多朋友来MAIL或流言告诉我说,VQF该怎么播放?这次我做了一个关于日本YAMAHA VQF播放器的
操作说明。06/19/2001 Kingda
2. 音频视频测试源搜集
目前在 F:\AVStuff 目录下共搜集了 8 种音频格式和 12 种视频格式
Audio A01.mp2 Video V01.mov
A02.mp3 V02.mp4
A03.ogg V03.mpeg
A04.rm V04.mpg
A05.vqf V05.asf
A06.wav V06.asx
A07.wma V07.avi
A08.au V08.wmv
V09.rmvb
V10.swf
V11.flc
V12.fli -
1. 什么是matroska?我听说它是一种容器格式?那是什么?
容器格式允许你组合不同的多媒体流(大多数是音频和视频)到一个单独的文件里。著名的多媒体容器格式有AVI(.avi),MPEG(.mpg/.mpeg),OGM(.ogm),MP4(.mp4) 和 Realmedia(.rm/.rmvb)
matroska是一个免费,开源的容器格式,在可扩展的基础上着力于提供老式格式象avi不具有的许多改进的特
性。matroska 支持将以下的东西封包,例如没有任何争议的可变比特率音频内容(VBR),可变帧率(VFR),段
落信息,文件附件,错误信息(EDC)和现代A/V codecs,象“高级音频编码AAC(Advanced Audio Coding)”,
“Ogg Vorbis”或“Realvideo 9” (RV9)所有AVI不具有的。2. 即席编辑技术(Ad-hoc)
在网页的相关内容所在位置可以马上编辑该信息,近期 del.icio.us 和 flickr.com 都采用了同样的技术,
让人感觉耳目一新,原理上讲的确很简单,典型“所见即所得”,此处可看作“所见即所编”,但其 UI 的
原创思想可谓 Web 设计上的一大进步。3. 关于技术委员会涉及的 IPO 输入输出问题沟通情况总结
操作对象:
技术研究课题、项目前期可行性分析与总体规划
输入 I:
新产品立项建议书
市场技术信息
项目总结报告
输出 O:
产品技术可行性分析
产品总体方案规划书
问题:
定位
产品变更 PCN 时涉及的内部无法解决的问题,是否需要技术委员会支援、联合攻关或联系外部支援?4. Miscs
主要数据结构
typedef struct VLC {
int bits;
VLC_TYPE (*table)[2]; ///< code, bits
int table_size, table_allocated;
} VLC;typedef struct RL_VLC_ELEM {
int16_t level;
int8_t len;
uint8_t run;
} RL_VLC_ELEM;监测函数
wmadec.c
tprintf
mplayer.c
mp_msg(MSGT_CPLAYER, MSGL_INFO, "BENCHMARKn: disp: %d (%3.2f fps) drop: %d (%d%%) total: %d (%3.2f fps)\n",
total_frame_cnt-drop_frame_cnt,
(total_time_usage>0.5)?((total_frame_cnt-drop_frame_cnt)/total_time_usage):0,
drop_frame_cnt, 100*drop_frame_cnt/total_frame_cnt,
total_frame_cnt, (total_time_usage>0.5)?(total_frame_cnt/total_time_usage):0);代码、数据及优化的关系
代码 wmadec.c 有 1400 行
而数据 wmadec.h 也有 1400 行VBR 比特率音频内容,VFR 可变帧率
gdb GNU/GCC 的 Debug 调试工具
suboptimal 不甚理想
Mplayer
最新推荐文章于 2024-09-28 07:31:12 发布