使用 v0.6 以後 (2010 09 23) 的 ffmpeg
ffplay 可以播放 1seg log stream..
9.24.2010
9.16.2010
5.17.2010
complian 一下 .... 無關的東西...其實是自己不好 XD
有點詞窮..
懷疑是不是故意的..
最好是 struct node* Platform 實際上是從 array Node 中挑出一個來的。
好像有用到 Singletone pattern,用 struct context *Context() 取出唯一的 context 指標。
用 C++寫就好,幹嘛要用C寫,然後又要做出C++的東西 (default constructer,class hierachy,function overwrite.. abstrator overwrite etc)。
用 define function 作 cast pointer 真是糟糕,看起來是 argument,卻拿來作 cast name。
然後整個 project sourcecode 就是 node 來 node 去的,什麼名字都有node,也就等於什麼名字都沒有 node...(難怪會重寫)
Module Name 先放在 string table裡,每個 id 代表一個 Module Name,然後再用 Id 來 load module。
還有..
nodedef : node的定義,包含..
又有node,又有 class,node define 的東西是 class。
static function,第一個 argument 在所有的caller 都是一樣的值,那為什麼不直接 reference ? 還要多一個標準?
NodeClass 就要用 FindClass 來操作。 -- 因為 FindClass 內部只對 NodeClass 這個 member 操作。(隱含的)
一堆 node, class 都 initial 完後,在 global unique variable - Context( ) 的 array xxx 就已經都註冊好所有 id 和對應的 create function。
NoteCreate( classid) 會從 context array 中找到那個 classid 的 node..
又是一個 特例。所以 interface 這個 node 要用 NodeCreate( ) 出來後,要手動 cast 成 (win*) 然後取出 Popup( )
{array Node;
...
struct node* Platform;
...} Node 這個詞到處在用,還分大小寫..當 structure name,又當 variable name...懷疑是不是故意的..
最好是 struct node* Platform 實際上是從 array Node 中挑出一個來的。
好像有用到 Singletone pattern,用 struct context *Context() 取出唯一的 context 指標。
用 C++寫就好,幹嘛要用C寫,然後又要做出C++的東西 (default constructer,class hierachy,function overwrite.. abstrator overwrite etc)。
用 define function 作 cast pointer 真是糟糕,看起來是 argument,卻拿來作 cast name。
然後整個 project sourcecode 就是 node 來 node 去的,什麼名字都有node,也就等於什麼名字都沒有 node...(難怪會重寫)
Module Name 先放在 string table裡,每個 id 代表一個 Module Name,然後再用 Id 來 load module。
還有..
stringdef Def;這樣的code..
stringdef* Ptr = &Def;
..
(,,, &Ptr,,,)
nodedef : node的定義,包含..
- load setting
- ID
- parent class (的ID)
- priority (?)
- 這個 node (class?) 的 create function
- delete function
又有node,又有 class,node define 的東西是 class。
static function,第一個 argument 在所有的caller 都是一樣的值,那為什麼不直接 reference ? 還要多一個標準?
NodeClass 就要用 FindClass 來操作。 -- 因為 FindClass 內部只對 NodeClass 這個 member 操作。(隱含的)
一堆 node, class 都 initial 完後,在 global unique variable - Context( ) 的 array xxx 就已經都註冊好所有 id 和對應的 create function。
NoteCreate( classid) 會從 context array 中找到那個 classid 的 node..
- LoadLibrary
- Call DLLRegister
- load parent class/node (recursive)
- call node 的 Create( )
又是一個 特例。所以 interface 這個 node 要用 NodeCreate( ) 出來後,要手動 cast 成 (win*) 然後取出 Popup( )
5.13.2010
notes - code reading of ffmpeg
AVCodec h264_decoder = {
"h264", //name
CODEC_TYPE_VIDEO, //type
CODEC_ID_H264, //id
sizeof(H264Context), //private data size
decode_init, // (*init)()
NULL, // (*encode)()
decode_end, // (*close)()
decode_frame, // (*decode)()
/*CODEC_CAP_DRAW_HORIZ_BAND |*/ CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY, //capability
NULL, //next
flush_dpb, // (*flush)()
};
5.12.2010
Try VLC for WINCE
雖然網站說 因為沒有 developer 對這個有興趣,所以ce 的 port 中止了,
但是還有是 for CE 的 nightly build 可以 download (不知道是不是因為 auto build 的關係)
http://nightlies.videolan.org/build/wince/?C=M;O=D
說明是 for XScale,還是 dowload 下來試試。
使用KITL 來 run ,結果有 message ; find no plugin, check --plugin-path
所以改用 target control 來 run , command:
結果 load lib555 出現 exception
變成
奇怪,fail在
但是還有是 for CE 的 nightly build 可以 download (不知道是不是因為 auto build 的關係)
http://nightlies.videolan.org/build/wince/?C=M;O=D
說明是 for XScale,還是 dowload 下來試試。
使用KITL 來 run ,結果有 message ; find no plugin, check --plugin-path
所以改用 target control 來 run , command:
>s SDMMC\vlc\vlc --plugin-path SDMMC\vlc\plugins就可以 load plugins 的 dll 了。
結果 load lib555 出現 exception
PB Debugger Loaded 'liblive555_plugin.dll', no matching symbolic information found.把lib555 拿掉試試看..
Exception 'Data Abort' (4): Thread-Id=059c003e(pth=8e23815c), Proc-Id=059b002a(pprc=8ddbc36c) 'vlc.exe',
VM-active=059b002a(pprc=8ddbc36c) 'vlc.exe'
PC=42f14df8(liblive555_plugin.dll+0x00084df8) RA=42f0a1a8(liblive555_plugin.dll+0x0007a1a8) SP=0011f848,
BVA=6d9dc460
Data Abort: 0xC0000005 0x42F14DF8
變成
PB Debugger Loaded 'libyuy2_i422_plugin.dll', no matching symbolic information found.一樣,rename掉,繼續..
PB Debugger Loaded 'libzip_plugin.dll', no matching symbolic information found.
Exception 'Raised Exception' (-1): Thread-Id=045f002e(pth=8e23815c), Proc-Id=05fc002a(pprc=8ddbc36c) 'vlc.exe',
VM-active=05fc002a(pprc=8ddbc36c) 'vlc.exe'
PC=4002c508(coredll.dll+0x0001c508) RA=93b3c4c8(kernel.dll+0x000064c8) SP=0011f648, BVA=ffffffff
奇怪,fail在
B Debugger Loaded 'libyuy2_i422_plugin.dll', no matching symbolic information found.猜是 memory 不夠的問題,刪掉一堆dll看看.
Exception 'Raised Exception' (-1): Thread-Id=0591003a(pth=8e23815c), Proc-Id=058a005a(pprc=8e946000) 'vlc.exe', VM-active=058a005a(pprc=8e946000) 'vlc.exe'
PC=4002c508(coredll.dll+0x0001c508) RA=93b3c4c8(kernel.dll+0x000064c8) SP=0011f648, BVA=ffffffff
5.10.2010
tcpmp for WINCE 6.0
tcpmp 啟動時會自動 load 目錄下所有的 *.plg 檔。
其實這些檔就是 DLL,但是為了防止load 到騎他program 的 DLL,所以rename 成 plg。
tcpmp 的 VS2005 project 是一個基本的 project,只包涵 network, mpeg1.. etc 等少數的 codec 在裡面,這些 codec project 會 build 成 *.plg 檔,放在 release/output folder 中。
其他 project (ffmpeg, aac, ac3..) 要 build 的話,可以直接開啟該 codec project 的 vcp (for eVC 得的那個,不是VC6的),然後修改一下:
也可以直接把project 加到 tcpmp 中。
tcpmp 有使用 類似 llvm 的技巧,在 port.h 中定義 CONFIG_DYNCODE。
undefine 的話就可以不用 (但是code 沒有很完全)。
tcpmp 啟動會 load *.txt ,這是原來在 language folder 下的 界面字串定義檔,所以也要 copy 到 執行目錄下。
其實這些檔就是 DLL,但是為了防止load 到騎他program 的 DLL,所以rename 成 plg。
tcpmp 的 VS2005 project 是一個基本的 project,只包涵 network, mpeg1.. etc 等少數的 codec 在裡面,這些 codec project 會 build 成 *.plg 檔,放在 release/output folder 中。
其他 project (ffmpeg, aac, ac3..) 要 build 的話,可以直接開啟該 codec project 的 vcp (for eVC 得的那個,不是VC6的),然後修改一下:
- 要 把 common.lib 加入 -- 要把 common.lib 所在path 加到 linker 的 Additional Library Direction 中。把 common.lib 加到 Linker - Input - Additional Dependency 中
- 修改 Linker - Output File : $(OutDir)\$(ProjectName).plg
- 修改 Linker - Debugging - Generate Program Database : $(OutDir)/ffmpeg.pdb
也可以直接把project 加到 tcpmp 中。
tcpmp 有使用 類似 llvm 的技巧,在 port.h 中定義 CONFIG_DYNCODE。
undefine 的話就可以不用 (但是code 沒有很完全)。
tcpmp 啟動會 load *.txt ,這是原來在 language folder 下的 界面字串定義檔,所以也要 copy 到 執行目錄下。
diff --git a/common/blit/blit_arm_fix.c b/common/blit/blit_arm_fix.c
index 7af2299..6131e95 100644
--- a/common/blit/blit_arm_fix.c
+++ b/common/blit/blit_arm_fix.c
@@ -25,7 +25,7 @@
#include "../dyncode/dyncode.h"
#include "blit_soft.h"
-#if defined(ARM)
+#if defined(ARM) && defined(CONFIG_DYNCODE)
typedef struct stack
{
diff --git a/common/blit/blit_arm_gray.c b/common/blit/blit_arm_gray.c
index 9b7797b..8d8b636 100644
--- a/common/blit/blit_arm_gray.c
+++ b/common/blit/blit_arm_gray.c
@@ -25,7 +25,7 @@
#include "../dyncode/dyncode.h"
#include "blit_soft.h"
-#if defined(ARM)
+#if defined(ARM) && defined(CONFIG_DYNCODE)
typedef struct stack
{
diff --git a/common/blit/blit_arm_half.c b/common/blit/blit_arm_half.c
index a59d66c..089109d 100644
--- a/common/blit/blit_arm_half.c
+++ b/common/blit/blit_arm_half.c
@@ -29,7 +29,7 @@
// DstAlignPos 4
// SrcAlignPos 2
-#if defined(ARM)
+#if defined(ARM) && defined(CONFIG_DYNCODE)
typedef struct stack
{
diff --git a/common/blit/blit_arm_packed_yuv.c b/common/blit/blit_arm_packed_yuv.c
index 494721b..871bd36 100644
--- a/common/blit/blit_arm_packed_yuv.c
+++ b/common/blit/blit_arm_packed_yuv.c
@@ -25,7 +25,7 @@
#include "../dyncode/dyncode.h"
#include "blit_soft.h"
-#if defined(ARM)
+#if defined(ARM) && defined(CONFIG_DYNCODE)
typedef struct stack
{
diff --git a/common/blit/blit_arm_rgb16.c b/common/blit/blit_arm_rgb16.c
index 3c153f1..6de28fb 100644
--- a/common/blit/blit_arm_rgb16.c
+++ b/common/blit/blit_arm_rgb16.c
@@ -25,7 +25,7 @@
#include "../dyncode/dyncode.h"
#include "blit_soft.h"
-#if defined(ARM)
+#if defined(ARM) && defined(CONFIG_DYNCODE)
// R0..R6 temporary
// R7 Pos(when Stretch)
diff --git a/common/blit/blit_arm_stretch.c b/common/blit/blit_arm_stretch.c
index 5855d9c..be36ed8 100644
--- a/common/blit/blit_arm_stretch.c
+++ b/common/blit/blit_arm_stretch.c
@@ -27,7 +27,7 @@
#include "../dyncode/dyncode.h"
#include "blit_soft.h"
-#if defined(ARM)
+#if defined(ARM) && defined(CONFIG_DYNCODE)
typedef struct stack
{
diff --git a/common/blit/blit_arm_yuv.c b/common/blit/blit_arm_yuv.c
index 3e4d612..38ae8cd 100644
--- a/common/blit/blit_arm_yuv.c
+++ b/common/blit/blit_arm_yuv.c
@@ -29,7 +29,7 @@
// DstAlignPos 8
// SrcAlignPos 8
-#if defined(ARM)
+#if defined(ARM) && defined(CONFIG_DYNCODE)
// R0..R4 temporary
// R5 DiffMask (when Diff)
diff --git a/common/blit/blit_soft.c b/common/blit/blit_soft.c
index 3b8770c..f4cb08f 100644
--- a/common/blit/blit_soft.c
+++ b/common/blit/blit_soft.c
@@ -1795,7 +1795,7 @@ static bool_t BlitCompile(blit_soft* p,
p->SrcPos[i] = BitMaskPos(p->Src.BitMask[i]);
}
-#if defined(ARM)
+#if defined(ARM) && defined(CONFIG_DYNCODE)
if ((p->Dst.Flags & PF_RGB) && p->Dst.BitCount==16 && !p->SrcYUV)
Any_RGB_RGB(p);
if (!p->SrcYUV && DstPlanarYUV && p->RScaleX==16 && p->RScaleY==16)
@@ -1848,11 +1848,14 @@ static bool_t BlitCompile(blit_soft* p,
}
#endif
+#if defined(ARM) && defined(CONFIG_DYNCODE)
+
CodeBuild(&p->Code);
if (p->Code.Size)
p->Entry = (blitsoftentry)p->Code.Code;
else
p->Entry = NULL;
+#endif
#if defined(_M_IX86) && !defined(TARGET_SYMBIAN)
diff --git a/common/blit/blit_wmmx_fix.c b/common/blit/blit_wmmx_fix.c
index 6ffb3bb..1b3ec38 100644
--- a/common/blit/blit_wmmx_fix.c
+++ b/common/blit/blit_wmmx_fix.c
@@ -32,7 +32,7 @@
// RScale==32 && !SwapXY 16x4 -> 8x2
// RScale==32 && SwapXY 4x16 -> 8x2
-#if defined(ARM)
+#if defined(ARM) && defined(CONFIG_DYNCODE)
typedef struct stack
{
diff --git a/common/cpu/cpu.c b/common/cpu/cpu.c
index a68bad6..6e410d1 100644
--- a/common/cpu/cpu.c
+++ b/common/cpu/cpu.c
@@ -64,8 +64,14 @@ void CPUDetect(cpudetect* p)
#ifdef ARM
p->Arch = T("ARM");
- SafeGetCpuId(0,CpuId);
+ //SafeGetCpuId(0,CpuId);
+ p->ICache = 16*1024;
+ p->DCache = 16*1024;
+ Caps |= CAPS_ARM_GENERAL;
+ p->Model = T("1020E");
+ Caps |= CAPS_ARM_5E;
+/*
if (CpuId[0])
{
p->ICache = 512 << ((CpuId[1] >> 6) & 7);
@@ -156,7 +162,7 @@ void CPUDetect(cpudetect* p)
}
}
}
-
+*/
#elif defined(MIPS)
SafeGetCpuId(0,CpuId);
p->Arch = T("MIPS");
diff --git a/common/pcm/pcm_arm.c b/common/pcm/pcm_arm.c
index 8ebe96e..269fdc1 100644
--- a/common/pcm/pcm_arm.c
+++ b/common/pcm/pcm_arm.c
@@ -25,7 +25,7 @@
#include "../dyncode/dyncode.h"
#include "pcm_soft.h"
-#if defined(ARM)
+#if defined(ARM) && defined(CONFIG_DYNCODE)
typedef struct stack
{
diff --git a/common/portab.h b/common/portab.h
index 3b47674..bce4701 100644
--- a/common/portab.h
+++ b/common/portab.h
@@ -71,7 +71,7 @@
#endif
#if defined(ARM) || defined(MIPS) || defined(SH3)
-#define CONFIG_DYNCODE
+#undef CONFIG_DYNCODE
#endif
#if defined(_M_IX86)
diff --git a/common/win32/platform_win32.c b/common/win32/platform_win32.c
index 0df8c42..78ae591 100644
--- a/common/win32/platform_win32.c
+++ b/common/win32/platform_win32.c
@@ -670,7 +670,7 @@ void Platform_Init()
BacklightEvent = CreateEvent(NULL, FALSE, FALSE, T("TIMEOUTDISPLAYOFF"));
- Power_Init();
+ //Power_Init();
#endif
if (!Context()->CodePage)
@@ -976,6 +976,7 @@ bool_t GetDisplayPower()
int SetDisplayPower(bool_t State,bool_t Force)
{
+/*
VIDEO_POWER_MANAGEMENT VPM;
HDC DC;
@@ -991,6 +992,7 @@ int SetDisplayPower(bool_t State,bool_t Force)
ExtEscape(DC, SETPOWERMANAGEMENT, sizeof(VPM), (LPCSTR) &VPM, 0, NULL);
ReleaseDC(NULL, DC);
}
+*/
return ERR_NONE;
}
diff --git a/common/win32/str_win32.c b/common/win32/str_win32.c
index 77bc3bf..04f8a34 100644
--- a/common/win32/str_win32.c
+++ b/common/win32/str_win32.c
@@ -24,6 +24,7 @@
#include "../common.h"
#include "../gzip.h"
+
#define MAXTEXT 20000
#if defined(TARGET_WIN32) || defined(TARGET_WINCE)
diff --git a/interface/win32/interface.c b/interface/win32/interface.c
index ac68894..375060f 100644
--- a/interface/win32/interface.c
+++ b/interface/win32/interface.c
@@ -2765,10 +2765,12 @@ static bool_t Proc(intface* p, int Msg, uint32_t wParam, uint32_t lParam, int* R
break;
case WM_KEYUP:
+/*
#if defined(TARGET_WINCE)
if (!GetDisplayPower())
SetDisplayPower(0,1);
#endif
+*/
Key = WinKeyState(KeyRotate(p,wParam));
for (i=0;i<HOTKEYCOUNT;++i)
if (p->HotKey[i] && (p->HotKey[i] & ~HOTKEY_KEEP) == Key)
@@ -2792,6 +2794,7 @@ static bool_t Proc(intface* p, int Msg, uint32_t wParam, uint32_t lParam, int* R
break;
case WM_HOTKEY:
+/*
#if defined(TARGET_WINCE)
if ((LOWORD(lParam) & MOD_KEYUP))
{
@@ -2800,7 +2803,8 @@ static bool_t Proc(intface* p, int Msg, uint32_t wParam, uint32_t lParam, int* R
}
else
#endif
- PostMessage(p->Win.Wnd,WM_COMMAND,wParam,0);
+*/
+ PostMessage(p->Win.Wnd,WM_COMMAND,wParam,0);
*Result = 0;
return 1;
diff --git a/interface/win32/win_win32.c b/interface/win32/win_win32.c
index 7c92a1f..821cbe4 100644
--- a/interface/win32/win_win32.c
+++ b/interface/win32/win_win32.c
@@ -2592,6 +2592,7 @@ static void HandleMessage(win* p,MSG* Msg)
{
int Result;
+/*
#if defined(TARGET_WINCE)
if (Msg->message == WM_HIBERNATE)
{
@@ -2599,7 +2600,7 @@ static void HandleMessage(win* p,MSG* Msg)
NodeHibernate();
}
#endif
-
+*/
if (Msg->message >= WM_APP + 0x200 &&
Msg->message <= WM_APP + 0x220)
{
5.07.2010
Log : trace tcpmp exception on CE 6.0 - assembly code
看一下 assembly code exception 的原因:
對應的 assmbly code是:
Entry( ) 內的 assembly code 是:
在 CompileCode( ), BuildCode( ) 完後,0x10A000 的內容:
可以看到是不一樣的,0x10A0000 到 0x10A000F 都被清成 0x00。
之後的 code 果然跟 cache 有關,code都做完後,就要:
在 msdn 這一頁 有列出,CacheSync 是 Kernel Mode Only.
p->Entry(p,Dst,Src,*DstLength,&p->State,Volume)
對應的 assmbly code是:
41041954 E59D3044 ldr r3, Volume, #0x44可以看到 參數傳遞是 r0~r3,stack,stack
41041958 E58D3004 str r3, [sp, #4]
4104195C E59D302C ldr r3, p, #0x2C
41041960 E2833004 add r3, r3, #4
41041964 E58D3000 str r3, [sp]
41041968 E59D3038 ldr r3, DstLength, #0x38
4104196C E5933000 ldr r3, [r3]
41041970 E59D2034 ldr r2, Src, #0x34
41041974 E59D1030 ldr r1, Dst, #0x30
41041978 E59D002C ldr r0, p, #0x2C
4104197C E59DE02C ldr lr, p, #0x2C
41041980 E59E4000 ldr r4, [lr]
41041984 E1A0E00F mov lr, pc
41041988 E1A0F004 mov pc, r4
Entry( ) 內的 assembly code 是:
010A0000 00000000 andeq r0, r0, r0看到好像argument 完全不對應,r0 甚至被破壞..
010A0004 00000000 andeq r0, r0, r0
010A0008 00000000 andeq r0, r0, r0
010A000C 00000000 andeq r0, r0, r0
010A0010 E59D4028 ldr r4, [sp, #0x28]
010A0014 E5947004 ldr r7, [r4, #4]
010A0018 E5948008 ldr r8, [r4, #8]
010A001C E59D002C ldr r0, [sp, #0x2C]
010A0020 E3570C01 cmp r7, #1, 24
010A0024 1A000006 bne 010A0044
010A0028 E0D920F2 ldrsh r2, [r9], #2
010A002C E0020290 mul r2, r0, r2
010A0030 E1A02442 mov r2, r2, asr #8
010A0034 E0CB20B2 strh r2, [r11], #2
010A0038 E15B000E cmp r11, lr
010A003C 1AFFFFF9 bne 010A0028
010A0040 E8BD9FF0 ldmia sp!, {r4 - r12, pc}
010A0044 E1A03428 mov r3, r8, lsr #8
010A0048 E1A03083 mov r3, r3, lsl #1
010A004C E19920F3 ldrsh r2, [r9, +r3]
010A0050 E0888007 add r8, r8, r7
010A0054 E0020290 mul r2, r0, r2
010A0058 E1A02442 mov r2, r2, asr #8
010A005C E0CB20B2 strh r2, [r11], #2
010A0060 E15B000E cmp r11, lr
010A0064 1AFFFFF6 bne 010A0044
010A0068 E8BD9FF0 ldmia sp!, {r4 - r12, pc}
在 CompileCode( ), BuildCode( ) 完後,0x10A000 的內容:
010A0000 F0 5F 2D E9 00 B0 91 E5 03 E0 8B E0 00 90 92 E5 ._-.............
010A0010 28 40 9D E5 04 70 94 E5 08 80 94 E5 2C 00 9D E5 (@...p......,...
010A0020 01 0C 57 E3 06 00 00 1A F2 20 D9 E0 90 02 02 E0 ..W...... ......
010A0030 42 24 A0 E1 B2 20 CB E0 0E 00 5B E1 F9 FF FF 1A B$... ....[.....
010A0040 F0 9F BD E8 28 34 A0 E1 83 30 A0 E1 F3 20 99 E1 ....(4...0... ..
010A0050 07 80 88 E0 90 02 02 E0 42 24 A0 E1 B2 20 CB E0 ........B$... ..
010A0060 0E 00 5B E1 F6 FF FF 1A F0 9F BD E8 00 00 00 00 ..[.............
可以看到是不一樣的,0x10A0000 到 0x10A000F 都被清成 0x00。
之後的 code 果然跟 cache 有關,code都做完後,就要:
void CodeUnlock(void* Code,int Size)很奇怪的是,如果在這其中 break 一下(用KITL),或是完成後,用 DebugWindow 的 Memory 來 check 一下,資料就會正確。
{
DWORD Protect;
VirtualProtect(Code,Size,PAGE_EXECUTE_READ,&Protect);
if (FuncCacheSync)
FuncCacheSync(CACHE_SYNC_INSTRUCTIONS);
}
真的是cache 的關係? 這個 ARM11 有L2 cache..
在 msdn 這一頁 有列出,CacheSync 是 Kernel Mode Only.
5.06.2010
Log : tcpmp - add ffmpeg codec support
將 ffmpeg project 加入 tcpmp 中。
因為這樣加入的不會有 tcpmp 的 project setting,所以要手動加入 common.lib 的 library path。
還要手動把 common.lib 加入 link library
還要手動設定 output path 到 tcpmp\... 下 (跟大家一樣)
tcpmp 啟動會自動 load 所有 *.plg 檔,所以 ffmpeg.plg 會被 load 進去。
開啟 MPEG2 file (DVD) 試試... 一樣發生 exception.. 好像跟 pcm 一樣,是在 assembly - entry( ) 的地方
因為這樣加入的不會有 tcpmp 的 project setting,所以要手動加入 common.lib 的 library path。
還要手動把 common.lib 加入 link library
還要手動設定 output path 到 tcpmp\... 下 (跟大家一樣)
tcpmp 啟動會自動 load 所有 *.plg 檔,所以 ffmpeg.plg 會被 load 進去。
開啟 MPEG2 file (DVD) 試試... 一樣發生 exception.. 好像跟 pcm 一樣,是在 assembly - entry( ) 的地方
Log : trace tcpmp exception on CE 6.0 - remove exception
只好啟動 KITL,作 單布執行。
中 發生 exception。
trace code,看到 pcm_arm.c
這個好像是在作 arm assembler.....
不知道這一段 assmbly code 為什麼不能在 CE 6.0 (或是因為 arm11 的關係?)。
在播放wav時,entry( ) 的內容是:
所以這一段不用 assembly code 改用 UniversalType( )
!!這樣就可沒有 exception 了。
- enable debug ouput ,rebuild all。
- copy all the files in release folder (其實重要的是 pdb) to WINCE600 project release folder
- copy language filt (*.txt) to release WINCE600 project release folder
- 啟動 KITL 連線,設定 player.exe, common.dll, interface.plg 都由 release folder 取得
- 啟動 target control,s player.exe
- 選一個 mp3 file
- exception 發生!!
- 從 call stack 看exception 位置
p->Entry(p,Dst,Src,*DstLength,&p->State,Volume);
中 發生 exception。
trace code,看到 pcm_arm.c
這個好像是在作 arm assembler.....
CodeStart(&p->Code);其中 PCMCompile()..
PCMCompile(p);
CodeBuild(&p->Code);
if (p->Code.Size)
p->Entry = (pcmsoftentry)p->Code.Code;
// dst pointers
I2C(LDR,R11,R1,0);
I3(ADD,R14,R11,R3); // dstend
// src pointers
I2C(LDR,R9,R2,0);
I2C(LDR,R4,SP,OFS(stack,State));
I2C(LDR,R7,R4,OFS(pcmstate,Step));
I2C(LDR,R8,R4,OFS(pcmstate,Pos));
不知道這一段 assmbly code 為什麼不能在 CE 6.0 (或是因為 arm11 的關係?)。
在播放wav時,entry( ) 的內容是:
10A0000 00000000 andeq r0, r0, r0
010A0004 00000000 andeq r0, r0, r0
010A0008 00000000 andeq r0, r0, r0
010A000C 00000000 andeq r0, r0, r0
010A0010 E59D4028 ldr r4, [sp, #0x28]
010A0014 E5947004 ldr r7, [r4, #4]
010A0018 E5948008 ldr r8, [r4, #8]
010A001C E59D002C ldr r0, [sp, #0x2C]
010A0020 E3570C01 cmp r7, #1, 24
010A0024 1A000006 bne 010A0044
010A0028 E0D920F2 ldrsh r2, [r9], #2
010A002C E0020290 mul r2, r0, r2
010A0030 E1A02442 mov r2, r2, asr #8
010A0034 E0CB20B2 strh r2, [r11], #2
010A0038 E15B000E cmp r11, lr
010A003C 1AFFFFF9 bne 010A0028
010A0040 E8BD9FF0 ldmia sp!, {r4 - r12, pc}
010A0044 E1A03428 mov r3, r8, lsr #8
010A0048 E1A03083 mov r3, r3, lsl #1
010A004C E19920F3 ldrsh r2, [r9, +r3]
010A0050 E0888007 add r8, r8, r7
010A0054 E0020290 mul r2, r0, r2
010A0058 E1A02442 mov r2, r2, asr #8
010A005C E0CB20B2 strh r2, [r11], #2
010A0060 E15B000E cmp r11, lr
010A0064 1AFFFFF6 bne 010A0044
010A0068 E8BD9FF0 ldmia sp!, {r4 - r12, pc}
所以這一段不用 assembly code 改用 UniversalType( )
#if 0 //(defined(ARM) || defined(SH3) || defined(MIPS)) && defined(CONFIG_DYNCODE)還要記得把 UniversalType( ) 的 define guard um-comment 掉。
CodeStart(&p->Code);
PCMCompile(p);
CodeBuild(&p->Code);
if (p->Code.Size)
p->Entry = (pcmsoftentry)p->Code.Code;
#else
p->SrcType = UniversalType(&p->Src);
p->DstType = UniversalType(&p->Dst);
p->Entry = PCMUniversal;
!!這樣就可沒有 exception 了。
tcpmp source code - use default language, exception
tcpmp 會利用 GetLocaleInfo( ) 來取得 platform 的語系資訊。
如過想要強制使用英文,可以修改 platform_win32.c 的 DefaultLang( ),強制 return LANG_DEFAULT 就可以。
tcpmp 還有一段 : SafeException( ) ,將整個 code body 包起來:
有關 ce 的 try except,在這一篇有說明 http://windows-ce-dox.net/MS.Press-Programming.Microsoft/html/ch087.htm
如過想要強制使用英文,可以修改 platform_win32.c 的 DefaultLang( ),強制 return LANG_DEFAULT 就可以。
tcpmp 還有一段 : SafeException( ) ,將整個 code body 包起來:
#define SAFE_BEGIN __try {
.... code body...
#define SAFE_END ;} __except (SafeException(_exception_info())) {}
SafeException( ) 的 funciton 是:int SafeException(void* p)就是把 exception 的資料存入 crash.txt。
{
EXCEPTION_POINTERS* Data = (EXCEPTION_POINTERS*)p;
stream* File;
tchar_t Path[MAXPATH];
if (Context())
{
GetDebugPath(Path,TSIZEOF(Path),T("crash.txt"));
File = StreamOpen(Path,1);
if (File)
{
void** Stack;
contextreg* r;
int No;
const uint8_t* ContextRecord = (const uint8_t*) Data->ContextRecord;
EXCEPTION_RECORD* Record = Data->ExceptionRecord;
tchar_t* Name;
int DllBase;
tchar_t DllName[MAXPATH];
StreamPrintf(File,T("%s %s crash report\n----------------------------\n"),
Context()->ProgramName,Context()->ProgramVersion);
switch (Record->ExceptionCode)
{
case STATUS_ACCESS_VIOLATION: Name = T("Access violation"); break;
case STATUS_BREAKPOINT: Name = T("Breakpoint"); break;
case STATUS_DATATYPE_MISALIGNMENT: Name = T("Datatype misalignment"); break;
case STATUS_ILLEGAL_INSTRUCTION: Name = T("Illegal instruction"); break;
case STATUS_INTEGER_DIVIDE_BY_ZERO: Name = T("Int divide by zero"); break;
case STATUS_INTEGER_OVERFLOW: Name = T("Int overflow"); break;
case STATUS_PRIVILEGED_INSTRUCTION: Name = T("Priv instruction"); break;
case STATUS_STACK_OVERFLOW: Name = T("Stack overflow"); break;
default: Name = T("Unknown"); break;
}
if (!NodeLocatePtr(Record->ExceptionAddress,DllName,TSIZEOF(DllName),&DllBase))
{
DllName[0] = 0;
DllBase = (int)Record->ExceptionAddress;
}
StreamPrintf(File,T("%s(%08x) at %08x (%s:%08x)"),Name,Record->ExceptionCode,Record->ExceptionAddress,DllName,DllBase);
if (Record->ExceptionCode == STATUS_ACCESS_VIOLATION)
{
if (Record->ExceptionInformation[0])
Name = T("Write to");
else
Name = T("Read from");
StreamPrintf(File,T("\n%s %08x"),Name,Record->ExceptionInformation[1]);
if (NodeLocatePtr((void*)Record->ExceptionInformation[1],DllName,TSIZEOF(DllName),&DllBase))
StreamPrintf(File,T(" (%s:%08x)"),DllName,DllBase);
}
// context
StreamPrintf(File,T("\n\ncpu dump:"));
for (r=Reg;r->Name;++r)
{
void* Ptr = *(void**)(ContextRecord+r->Ofs);
StreamPrintf(File,T("\n%-5s = %08x"),r->Name,Ptr);
if (NodeLocatePtr(Ptr,DllName,TSIZEOF(DllName),&DllBase))
StreamPrintf(File,T(" (%s:%08x)"),DllName,DllBase);
}
if (r->Ofs >= 0)
{
StreamPrintf(File,T("\n\nstack dump:"));
Stack = *(void***)(ContextRecord+r->Ofs);
for (No=0;No<256;++No,++Stack)
{
if (!IsBadReadPtr(Stack,sizeof(void*)))
{
void* Ptr = *Stack;
StreamPrintf(File,T("\n%08x %08x"),Stack,Ptr);
if (NodeLocatePtr(Ptr,DllName,TSIZEOF(DllName),&DllBase))
StreamPrintf(File,T(" (%s:%08x)"),DllName,DllBase);
}
else
StreamPrintf(File,T("\n%08x ????????"),Stack);
}
}
StreamPrintf(File,T("\n\n"));
TRY_BEGIN
{
NodeBroadcast(NODE_CRASH,NULL,0);
}
TRY_END
NodeDump(File);
StreamClose(File);
}
MessageBox(NULL,LangStr(PLATFORM_ID,PLATFORM_CRASH_MESSAGE),
LangStr(PLATFORM_ID,PLATFORM_CRASH_TITLE),MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_ICONSTOP);
}
Mem_Done(); // use safevirtualfree (if done by OS, it could be buggy on O2 Atom)
TerminateProcess(GetCurrentProcess(),1);
return 1;
}
有關 ce 的 try except,在這一篇有說明 http://windows-ce-dox.net/MS.Press-Programming.Microsoft/html/ch087.htm
Log : trace tcpmp exception on CE 6.0 SetKMode
在 CE 6.0 不能 run 的原因好像是 SetKMode( ) 嗎?
雖然 SetKMode 在 CE 6.0 已經不支援了,但是 CoreDll.dll 裡還是找得到 function。
SetKMode( ) 在 DetectCPU() 中使用,主要在知道 cpu type,設定好一堆 instruction capabilty。
這樣之後的一堆 image process 會依照 cpu 的 capability (指令集) 決定 code。
只好 hard code
if ((CpuId[0] & 0xFF000000) == 0x41000000) //arm { Caps |= CAPS_ARM_GENERAL; switch ((CpuId[0] >> 4) & 0xFFF) { case 0x920: p->Model = T("920T"); break; case 0x922: p->Model = T("922T"); break; case 0x926: p->Model = T("926E"); Caps |= CAPS_ARM_5E; break; case 0x940: p->Model = T("940T"); break; case 0x946: p->Model = T("946E"); Caps |= CAPS_ARM_5E; break; case 0xA22: p->Model = T("1020E"); Caps |= CAPS_ARM_5E; break; } }還有
if (CpuId[0]) { p->ICache = 512 << ((CpuId[1] >> 6) & 7); p->DCache = 512 << ((CpuId[1] >> 18) & 7); }所以直接寫
p->ICache = 16*1024; p->DCache = 16*1024; Caps |= CAPS_ARM_GENERAL; p->Model = T("1020E"); Caps |= CAPS_ARM_5E;其他的 code 都不要了。
這樣 exception 就沒了。
Log : Build tcpmp - part II . exception on SetKMode
在 CE 6.0 不能 run 的原因好像是 SetKMode( ) 嗎?
雖然 SetKMode 在 CE 6.0 已經不支援了,但是 CoreDll.dll 裡還是找得到 function。
SetKMode( ) 在 DetectCPU() 中使用,主要在知道 cpu type,設定好一堆 instruction capabilty。
這樣之後的一堆 image process 會依照 cpu 的 capability (指令集) 決定 code。
只好 hard code
if ((CpuId[0] & 0xFF000000) == 0x41000000) //arm { Caps |= CAPS_ARM_GENERAL; switch ((CpuId[0] >> 4) & 0xFFF) { case 0x920: p->Model = T("920T"); break; case 0x922: p->Model = T("922T"); break; case 0x926: p->Model = T("926E"); Caps |= CAPS_ARM_5E; break; case 0x940: p->Model = T("940T"); break; case 0x946: p->Model = T("946E"); Caps |= CAPS_ARM_5E; break; case 0xA22: p->Model = T("1020E"); Caps |= CAPS_ARM_5E; break;} }
還有
if (CpuId[0])
{ p->ICache = 512 << ((CpuId[1] >> 6) & 7);p->DCache = 512 << ((CpuId[1] >> 18) & 7);
}
所以直接寫
p->ICache = 16*1024;
p->DCache = 16*1024;
Caps |= CAPS_ARM_GENERAL;
p->Model = T("1020E");Caps |= CAPS_ARM_5E;
其他的 code 都不要了。
這樣 exception 就沒了。
... 然後第二個 exception 出現....
5.05.2010
Log : Build tcpmp
tcpmp 0.72RC1 source code 的 download 位置是: http://picard.exceed.hu/tcpmp/test/
查到好像是在 Platform_Init ( ) 裡的 NodeRegisterClass(&Platform) 裡。
但是同一function : NodeRegisterClass
死在 CallCreate( ) ,這是一個 recursive 程式。
tcpmp 的開發已經終止,原公司開發 betaplayer,即將 opensource (?)
開啟 tcpmp.sln 看,是 visual studio V9.0 ,所以使用 VS2005 開啟。
build - 選 pocket pc 2003 (ARMV4) 版本build OK。
===> 但是 在 CE 5.0 上不能run,連 launch 都不行
發現是 load Interface.plg fail -- 根本沒有這個檔。
follow readme,用 eVC d開啟,雖然 build fail,但是有出現 interface.plg 在 output folder。
查看發現, interface 這個 subproject 有設定 output name 是 interface.plg (所以應該是 Dll rename 的)
看VS2005 的 interface subproject,也有設定 output name 是 plg。
==>在 "packet pc 2003 (armv4)\debug" 下有 interface.plg
copy 到 SD card 上後,player.exe 果然 run 起來,接著出現 exception.. 畫面顯示: Language files (*.txt, *.tgz) ar missing.
搜尋*.txt,在 lang 這個 folder 裡有很多語系的 txt file,都 copy 到 SD 上, run player .exe 就沒有 error message 了。
在 CE 5.0 上 run OK,還可以開 WAVE file 播放,但是在 CE 6.0 就會有問題。
在 CE 5.0 上 run OK,還可以開 WAVE file 播放,但是在 CE 6.0 就會有問題。
==>有 exception :
Exception 'Undefined Instruction' (1): Thread-Id=058e007a(pth=8db9e7c8), Proc-Id=0563008a(pprc=8dd91000) 'PLAYER.EXE', VM-active=0563008a(pprc=8dd91000) 'PLAYER.EXE'
PC=41067188(common.dll+0x00097188) RA=41067498(common.dll+0x00097498) SP=0003fa8c, BVA=00000000
查到好像是在 Platform_Init ( ) 裡的 NodeRegisterClass(&Platform) 裡。
但是同一function : NodeRegisterClass
死在 CallCreate( ) ,這是一個 recursive 程式。
訂閱:
文章 (Atom)