Sep 23

EP翻墙法:OpenVPN+FoxyProxy

之前一直没用过VPN翻墙,因为VPN需要手动打开关闭,对我等用惯FG+FoxyProxy自动切换的人来说实在是很麻烦。。。(话说我连FG都设成服务让它自动启动了。。。

不过最近60大寿,FG和U相继RP,基本是没法用了。前两天实在无法忍受墙内的日子,弄了个OpenVPN回来研究,EP了半天终于研究出来了。。。

说起来原理其实很简单,只要不让OpenVPN修改全局路由,然后弄个代理服务器程序把本地端口绑定到虚拟网卡就可以了。不过这程序倒是费了一番周折,Google根本找不到小型能指定本地绑定ip的代理服务器。。。最后只好自己写一个。。。

不罗嗦了,这里简单说下步骤:

  1. 配置OpenVPN到可用状态,Google很多教程,这里就不说了。目前我用过AlonWebUltraVPN的服务,感觉上UltraVPN快一点,而且没有广告。
  2. 在配置文件加上以下内容(如有重复可以删除,路径请自行修正):
    route-noexec
    
    route-up "cmd /c D:\\OpenVPN\\config\\runproxy.cmd"
    
    script-security 3 system
    
    down "cmd /c taskkill /f /im proxy.exe & echo DOWN"
  3. runproxy.cmd(注意if后面的数字要改成自己机器虚拟网卡的编号,可在CMD运行Route print查看):

    @echo off 
    cd /d "%~dp0"
    route delete %route_network_1% mask %route_netmask_1%  if 32
    route delete 0.0.0.0 mask 0.0.0.0  if 32
    
    
    route add %route_network_1% mask %route_netmask_1% %route_gateway_1% metric 1 if 32
    route add 0.0.0.0 mask 0.0.0.0 %route_vpn_gateway% metric 1 if 32
    
    taskkill /f /im proxy.exe
    start proxy.exe %ifconfig_local%
  4. 启动OpenVPN后,把FoxyProxy的代理设置为127.0.0.1:8119即可。

 

配置模板、代理程序及源代码

(代理程序需要.Net 2.0)

祝各位翻墙愉快。。。

Across the Great FireWall we can reach every corner in the world.

Aug 13

小记:MPlayer的承载窗口不支持透明

准确来说,是不支持WS_EX_LAYERED属性。。。如果使用的话,某些机器(据我所知主要为XP系统。。。我的Vista和Win7都没出现。。。orz)有可能会出现以下情况:

  1. 窗口闪动
  2. 画面错误(颜色/大小等)
  3. DirectX非加速输出无法使用(诡异的是加速就没问题。。。
  4. Mplayer崩溃(某台机器上用gl输出的话一定会出现。。。)

 

解决方法很简单。。。就是不要用这属性(拖走)。。。顺带连TransparencyKey和Opacity也不能用了。。。orz

已经被这问题困扰很久了。。。最崩溃的是在我的机器上完全正常。。。到其它人那才会出问题。。。搞得调试也非常麻烦。。。orz

接着还得头疼怎么把窗口四周的圆角弄回来。。。难道真的要逼我改皮肤么。。。囧

Jun 22

网易有道难题。。。止步于复赛。。。

昨晚看见第3题就囧了。。。套用某人一句话。。。这俨然不是为我等小菜准备的。。。

做好前两道题用了1小时左右。。。剩下的时间都浪费在第3道上了。。。没做完是一定的。。。结果系统测试的时候第2题挂掉了。。。orz

下来以后越想越郁闷。。。第2题估计就是漏了一个处理。。。如果直接放弃第3题的话应该是可以检查出来的。。。

只能说经验不足了。。。其实第一次参加编程比赛。。。这个成绩也是意料之内。。。下次再接再厉了。。。

第一题代码:

    Public Function getNext(ByVal A As Long) As Long


        A += 1 ' bigger than a
        Dim sA As String = A.ToString()

        Dim i As Integer
        For i = 0 To sA.Length - 2
            If sA(i) = sA(i + 1) Then
                Exit For
            End If
        Next
        If i = sA.Length - 1 Then
            Return A ' A is non repeating number
        End If
        Dim leftPart As Long = (Long.Parse(sA.Substring(0, i + 1)))
        Dim rightPart As New System.Text.StringBuilder
        Dim isZero As Boolean = True

        Dim rightFirst As Long = Long.Parse(sA(i + 1)) + 1
        If rightFirst > 9 Then
            rightFirst = 0
            leftPart = getNext(leftPart)
            Dim newA As String = leftPart & rightFirst
            If i + 2 < sA.Length Then
                newA = newA & sA.Substring(i + 2)
            End If
            Return getNext(Long.Parse(newA))
        End If

        rightPart.Append(rightFirst)
        For j As Integer = i + 2 To sA.Length - 1
            If isZero Then
                rightPart.Append("0")
            Else
                rightPart.Append("1")
            End If
            isZero = Not isZero
        Next
        Return Long.Parse(leftPart & rightPart.ToString())

    End Function

 

第二题:

 

	Public Function maximize(ByVal word As String, ByVal maxChanges As Integer) As Integer


        If word.Length = 1 Then
            Return 1
        End If
        Dim counts As IDictionary(Of Char, Integer) = CountChars(word)
        Dim chars As Char() = word.ToCharArray()
        Dim changes As Integer = 0
        For i As Integer = 0 To word.Length \ 2
            If chars(i) <> chars(chars.Length - i - 1) Then
                If changes = maxChanges Then
                    'not a palindrome
                    Return 0
                End If
                changes += 1
		' 这里我忘记修正字符数了。。。应该就是这个原因而挂掉了。。。迟一点要去平台再试试。。。
                If counts(chars(i)) > counts(chars(chars.Length - i - 1)) Then
                    chars(chars.Length - i - 1) = chars(i)
                Else
                    chars(i) = chars(chars.Length - i - 1)
                End If
            End If
        Next
        If changes = maxChanges Then
            Return Score(New String(chars))
        ElseIf (chars.Length And 1) = 1 Then
            Return 1
        Else
            Return maximize(New String(chars, 0, chars.Length \ 2), maxChanges - changes) + 1
        End If
    End Function

    Private Function CountChars(ByVal word As String) As IDictionary(Of Char, Integer)
        Dim charCounts As New SortedList(Of Char, Integer)
        For Each ch As Char In word
            If charCounts.ContainsKey(ch) Then
                charCounts(ch) += 1
            Else
                charCounts(ch) = 1
            End If
        Next
        Return charCounts
    End Function

    Private Function Score(ByVal word As String) As Integer
        For i As Integer = 0 To word.Length \ 2
            If word.Chars(i) <> word.Chars(word.Length - i - 1) Then
                Return 0 ' not a palindrome
            End If
        Next
        If (word.Length And 1) = 1 Then
            Return 1 ' odd length
        Else
            Return Score(word.Substring(word.Length \ 2)) + 1
        End If
    End Function
May 12

杂记两则

很久没有发文了。。。于是记一下最近捣鼓项目的经验。。。

1、缩小Mplayer体积

Mplayer默认编译版有10MB之巨。。。其实有很多功能是不需要的,特别是我这个项目定死了视频的编码,更是可以把没用的编码全部禁用。要点有两个:

(1) FFMpeg单独编译

Mplayer虽然内置了FFmpeg,但是配置非常不方便,而且没用的功能禁用不干净。。。单独编译的时候,只需要几行参数就可以禁掉所有东西,在后面再启用需要的功能就可以了。

编译的时候要注意,光禁用_a结尾启用_so结尾的参数还不够,要手动指定库路径才能正常链接(也可能是我这的MinGW有问题。。。)。如:

--disable-libavutil_a   \
--disable-libavcodec_a   \
--disable-libavformat_a  \
--disable-libpostproc_a   \
--disable-libswscale_a    \
--enable-libavutil_so   \
--enable-libavcodec_so   \
--enable-libavformat_so  \
--enable-libpostproc_so   \
--enable-libswscale_so    \
--extra-libs-mplayer="/local/lib/libavformat.a /local/lib/libavcodec.a /local/lib/libswscale.a /local/lib/libpostproc.a /local/lib/libavutil.a" \

另外库的顺序非常重要,错了链接就会不成功。(想当初我试了N次才试出这个顺序。。。

(2) 编译后删除所有内嵌符号

这个是我最近才发现的,原来gcc会在输出文件中内嵌调试符号。。。直接导致程序大幅膨胀。这些符号基本是没有用处的(很少会有人在Windows用gdb调试吧。。。),完全是浪费空间。

还好删除符号也很简单,在Cygwin或MinGW环境下运行以下命令就可以了:

strip --strip-all <输出文件名>

弄完这些之后,MPlayer就只剩下5MB左右了,足足缩小了50%,而且基本的功能也不会缺少。

 

 

2、使Mono支持加载路径包含非ASCII字符的程序集

于是这个应该是很老的bug了,但是修复起来很简单。。。patch已经发到mono开发组了,希望下个版本可以包含吧。

2.4的Patch:

--- E:/image-2.4.c	四 四月 30 15:39:45 2009
+++ E:/image.c	四 四月 30 15:46:49 2009
@@ -878,11 +878,23 @@
 	MonoImage *image;
 	FILE *filed;
 	struct stat stat_buf;
-
+#ifdef PLATFORM_WIN32
+	gsize bytes_written;
+	gchar *fname_ansi = g_locale_from_utf8 (fname, -1, NULL, &bytes_written, NULL);
+	filed = fopen (fname_ansi, "rb");
+	g_free (fname_ansi);
+	if (filed == NULL){
+#else
 	if ((filed = fopen (fname, "rb")) == NULL){
+#endif // PLATFORM_WIN32
 		if (IS_PORTABILITY_SET) {
 			gchar *ffname = mono_portability_find_file (fname, TRUE);
 			if (ffname) {
+#ifdef PLATFORM_WIN32
+				gchar *ffname_utf8 = ffname;
+				ffname = g_locale_from_utf8 (ffname_utf8, -1, NULL, &bytes_written, NULL);
+				g_free (ffname_utf8);
+#endif // PLATFORM_WIN32
 				filed = fopen (ffname, "rb");
 				g_free (ffname);
 			}

 

由于在SVN的代码中fopen的调用改到另一个地方了,所以需要另一个patch:

--- E:/mono-filemap.c	三 四月 29 20:05:26 2009

+++ E:/mono-filemap-2.c	三 四月 29 20:11:35 2009

@@ -25,7 +25,17 @@

 MonoFileMap *
 mono_file_map_open (const char* name)
 {
-	return (MonoFileMap *)fopen (name, "rb");
+#ifdef PLATFORM_WIN32
+	// fopen in msvcrt.dll accepts ANSI string, but name is UTF-8 encoded
+	gsize bytes_written;
+	gchar *name_utf8 = name;
+	name = g_locale_from_utf8 (name_utf8, -1, NULL, &bytes_written, NULL);
+#endif // PLATFORM_WIN32
+	MonoFileMap *map = (MonoFileMap *)fopen (name, "rb");
+#ifdef PLATFORM_WIN32
+	g_free (name);
+#endif // PLATFORM_WIN32
+	return map;
 }
 
 guint64 

 

应用之后参照Mono主页的教程在Cygwin编译就可以了。(编译好要记得删符号。。。不然mono.dll会比发布版大N倍。。。

Mar 12

I264项目开发流水帐

于是认证考试终于告一段落了,前段时间接下来的项目也终于可以上马了。。。第一次做这么大的项目,正好可以实践之前学到的知识。。。

在这里记录下这次开发的进程,留待以后总结经验。。。

项目一句话简介:P2P视频播放器及服务器端

3.11-3.12:客户端组件关系图

这次把播放器的各个部分都组件化,期望能达到各个组件可以随意替换的效果。。。顺便练习了一下UML。。。

3.12:接口设计

3.13-3.15:播放器核心(其实就是MPlayer的包装。。。

3.16-3.18:网络传输库测试

网络传输部分计划使用修改过的BT协议,使用UDP传输。于是搞了几个udp可靠传输的框架下来测试。。。最终选定了UDT。测试的时候还发现默认的阻塞处理有问题,带宽浪费十分严重,有一次还把路由搞挂了。。。捣鼓了半天换上了TCP的阻塞控制算法,顺便还把keep-alive包的发送间隔改了。。。

3.18-3.19:数据转接层

3.20-3.24:MonoTorrent的UDT支持

弄这东西的时候发现UDT的Wrapper有一大堆bug。。。另外连那个TCP算法类也有bug。。。调试死了很多脑细胞。。。orz

3.25-3.27:网络传输组件

基本就是把bt组件封装一下,实现预先设计好的接口。看起来很简单,但是弄的时候才发现很麻烦。。。首先是发现mplayer的连接超时值是硬编码在代码里面的(BS啊。。。),在缓冲的时候就直接断掉了,逼着我改源代码。。。然后就是获取MonoTorrent下载好数据的代码弄了很久,最后发现直接FileStream打开就可以了。。。开始的时候想得太复杂了。。。

3.27-3.31:部分bug修复及改进

4.1-4.5:内网穿透

4.5-4.7:测试版准备

4.8-4.9:Mono兼容性修复。。。

之前以为mono就算不比.net原生慢,最多也是差不多速度。但测试下来发现窗体的响应速度mono居然要比原生.net还要快。。。算个意外收获吧,可是兼容性依然是个问题。。。最麻烦的一个问题是程序退出的时候90%会崩溃,10%进程无法退出。。。跟踪来跟踪去只发现貌似和线程池有关。。。为了不影响进度,只好暂时在窗体关闭的时候强制退出进程了。迟点再看看有没有办法修复。。。

4.9:内测版发布

4.10:修复mono引导器的bug。。。

4.12:修复退出时崩溃的bug

之前死活找不出哪里有问题,只好编译个mono来调试了。。。

Update: 搞了半天崩溃原来是mono跟踪的bug。。。进程残留是没有清理完成。。。orz

4.13-4.14:bug修复

4.15-4.20:播放器界面组件化及进程分离

进程的远程调用使用了Remoting,然后远程调用的类里有事件,于是事情就混乱了。。。搞了很多天。。。最终使用了双层包装来解决。。。迟一点等有空写一下实现细节吧。。。orz

4.21-4.25:播放器辅助功能

4.25:alpha 2发布

5.1:红眼病终于好点了。。。于是继续弄。。。

前两天修复了mono没法在中文路径下启动的bug,顺便提交到了官方。其实这个bug修复很简单,很奇怪为什么这么久都没人修复。。。

5.5:Alpha3发布

Mar 11

MCPD: Windows Developer 3.5达成。。。

恩。。。昨天把3科一天考完了。。。本来是预约了两天的,不过考场允许一次考掉,就不跑两趟了。。。虽然563有好几题不是很确定,不过还是全部拿到了900+。。。505和563的题目和2.0版的完全不同,多了很多关于3.5新特性还有SQL Server 2008的题目。。。想找题库的朋友就要再等一段时间了。。。

顺便BS下那考场。。。那电脑屏幕能闪得人泪流满面。。。orz

Feb 18

用于MKV内嵌的字体精简工具[2011-12-03更新]

2011-12-03:之前修改过代码忘记发布了,经taro( @06_taro )提醒才想起来orz

能想起来的改动:

* 在转换后的ASS内记录字体名字映射

其它的懒得去翻log了(死

 

这次主要的改进是加入字体名称随机化功能,可以解决字体残留所带来的影响。暂时没发现其它的副作用。。。

6.21:发现SSARepFont的帮助太简单。。。加了点内容。。。

7.11:GUI更新。。。支持字体名称随机化了。。。

09.2.18:小更新。。。修复了x64系统下不能运行的问题。。。(感谢squallatf!)

3.1:更新支持TTC格式。。。(其实很容易。。。之前一直懒得弄。。。orz

能根据字幕的内容删除字体中无用的字符,把字体缩小。测试显示1集正常动画的字幕所需字体的大小为原来的1/10左右,相对于MKV大小基本可以忽略了。配合附带的SSATextRip可以为特效和正文分别制作精简版字体。

好吧,其实也并不是只能用于MKV内嵌字体,虽然我也没想到其它用途。。。

点击这里下载

 

系统需求:Windows XP或以上,.Net Framework 2.0

更新日志:

SubsetFont:

1.1.3:

支持TTC格式

1.1.2:

修复了x64系统下不能运行的问题

1.1.1:

之前字体名称随机化后有一处校验和未重新计算,已修正(话说貌似没什么程序会去校验。。。

1.1.0:

新增功能:

字体名称随机化(-randomize, -r),可配合附带工具SSARepFont将SSA/ASS文件内的字体名称一同修改。(GUI暂时不支持此功能,可参考附带的范例来创建批处理)

预览输出字体(-preview, -p)

1.0.1:处理过程中输出更多信息

1.0.0:显示未包含在新字体里的字符(出现这种情况基本是因为那些字符原字体里面也没有。。。

0.9.0:在漫游发布的初始版本

 

SSATextRip:

1.0.2:修正非系统代码页的文件输出错误的问题

1.0.1:修正一处笔误。。。orz

GUI:

1.0.3:兼容性及其它小更新

1.0.2:支持字体名称随机化

1.0.1:支持创建批处理

Feb 12

第一个实用(?)的.Net AVS插件 – EPTextSub(EP特效内嵌插件。。。)

最近受人所托,压一个非常ep的特效,足有200MB+。。。估计是VSFilter内存泄漏的缘故,其中某几个部分压的时候内存占用会飙升,导致内存不足而crash。。。(据说某个part没人压成功过。。。

后来经过试验,发现一个非常EP的解决方法,就是分段压制。。。压最BT的part的时候,要分成每6帧一段。。。因为觉得分段和合并非常麻烦,于是这个插件就出现了。。。

使用方法:

 

#请预先加载VSFilter.dll
SetMemoryMax(16) #非必要,但推荐这么做 
LoadPlugin("AvsFilterNet.dll")
#…
EPTextSub(字幕文件[,内存限制]) #内存限制单位为MB,默认1024
# 或
EPEval("""TextSub(xxx)"""[,内存限制]) 

 

然后当压制程序的内存占用达到内存限制值时,就会自动重新加载字幕以释放VSFilter占用的内存。。。(顺便提一下,如果字幕文件非常巨大的话。。。压制进程可能会停顿N分钟。。。

 

下载:

 

 

 

 

(2.13小更新,主要是引入更简便的AVSValue释放机制。。。其它部分无改动。。。

2011-12-06:增加EPEval,其实也是很久以前写好的,忘记更新这里了orz

 

使用时的截图:

image

心电图

某人语。。。

 

系统需求:

.Net Framework 2.0+

如果安装.Net后还是不能运行的话,就要装这个:

Visual C++ 2008 SP1 Redistributable

 

最后,让我们期待下roozhou大对VSFilter的优化吧。。。orz