多谢tianalexander@gmail.com给我提供了FFMPEG在VC上的工程,节省了我很多时间。这个程序我很快就在VC上面跑起来,但是移植到EVC下面,中间经历了很多问题,花了3天才解决,有了不少心得体会。和大家交流一下。其实开源的TCPMP的新版本已经加入了FFMPEG这个插件,并且已经将很多运算用汇编优化的很好,由于这里我们需要对自己的编码网络包进行传送和解码,并且TCPMP体系庞大,所以还是自己使用解码函数这样来做,灵活性更强。tian提供的工程很好,很快就可以在VC上跑起来。但是移植到EVC,出了很多问题。经过不断的调试修改,我觉得主要的问题有两个,一个是在数据类型转换时的内存对齐问题,一个是64位整数乘法的问题。这个问题主要体现在fill_rectangle这个函数当中,原来的函数是这样的:static inline void fill_rectangle(void *vp, int w, int h, int stride, uint32_t val, int size){ //FIXME ensure this IS inlined uint8_t *p= (uint8_t*)vp; assert(size==1 || size==4); w *= size; stride *= size; //FIXME check what gcc generates for 64 bit on x86 and possible write a 32 bit ver of it …… }else if(w==8 && h==4){ *(uint64_t*)(p + 0*stride)= *(uint64_t*)(p + 1*stride)= *(uint64_t*)(p + 2*stride)=// *(uint64_t*)(p + 3*stride)= size==4 ? val*0x0100000001ULL : val*0x0101010101010101ULL; *(uint64_t*)(p + 3*stride)= size==4 ? val*0x0100000001 : val*0x0101010101010101; }else if(w==16 && h==2){ *(uint64_t*)(p + 0+0*stride)= *(uint64_t*)(p + 8+0*stride)= *(uint64_t*)(p + 0+1*stride)=// *(uint64_t*)(p + 8+1*stride)= size==4 ? val*0x0100000001ULL : val*0x0101010101010101ULL; *(uint64_t*)(p + 8+1*stride)= size==4 ? val*0x0100000001 : val*0x0101010101010101; ……}注意这里用了很多强制类型转换,在编译的时候,没有错误,但是在ARM上运行的时候,可能因为ARM寻址指令的问题,会出现data type misalignment错误,所以先将这里改成了复制内存的方式。其实这里如果一开始就使用FFMPEG提供的汇编写的这个函数,就不会出任何问题,不过这样64位整数在EVC乘法的问题我就不会发现了。我在这里能够运行之后,总是解码头帧正确,从第二帧开始出错,跟踪了一下午,才发现原来是这个函数里面的64位整数乘法,如果不用64位变量而只用立即数进行运算,返回的是32位整数,所以这里又这样修改了一下,结果才正确。这个是程序和测试用例,可以用X264这个程序来将YUV制作为264编码文件。本程序是纯C的,所以PPC上400M只能做到11FPS左右,不过我会用TCPMP/FFMPEG里面的汇编继续优化。(很偷懒,呵呵)