(原)关于ffmpeg使用custom io-context遇到的一些坑

今天在使用android-as_video_player这个开源的框架来实现自己项目中的一个播放器,中间关于ndk编译ffmpeg遇到的坑,现在想起来,对ndk的心态,现在心里都有一万个cnm在奔腾,此处略过ndk编译ffmpeg源码的过程,最后使用的ndk-r10d编译的ffmpeg2.8.5版本。其实这时候ffmpeg已经更新到了4.1版本,要求别这么多,先将就着作用。
第一个坑就是当我把代码码完了,lib也编译通过,程序也能调试了的时候,心里是愉悦的,但跑起来以后,运行不正常,本地文件视频播放不出来,这就很尴尬了哈。
然后通过接口观察数据,发现avformat_open_input这个接口失败了,然后呢?报错信息调试为:Invalid data found when processing input,于是百度,谷歌搜索一番先,然后大部分人说调用的lib被协议部分被禁用的原因,于是就有了自己ndk编译ffmpeg这么操蛋的事情发生了。可我自己编译的lib怎么也不行呢?搞了半天,没办法,自己先阅读一通ffmpeg源码,然后发现还是找不到问题,于是想起来,我可以给ffmpeg设置一个log的回调函数,然后把错误信息报错的更加详细一些,于是加log回调函数,然后获取报错信息: moov atom not found,然后又baidu,google一番,少有收获哈,在https://bbs.csdn.net/topics/300243359论坛上找到第一条有用的信息。
 
 
 
原因是lseek函数在custom的接口中实现的有问题。
而从ffmpeg的源码,我们获取这个报错的信息位置为:
 
 
 
因为mp4文件,moov在文件的末尾,所以这个地方可以判断可能真的是lseek的原因。
然后加断点,发现我写的seek函数在whence等于AVSEEK_SIZE的时候,返回的-1。那custom方式的seek到底怎么实现呢?
经过参考http://www.52ffmpeg.com/article/497.htmlhttps://www.codeproject.com/Tips/489450/Creating-Custom-FFmpeg-IO-Context这两个文件,AVSEEK_SIZE这whence应该是返回文件的大小,同时seek我们也可以参考代码自己实现一个;
于是我自己的实现方式:
 1 int FileSource::ReadSeek( int offset, int whence){
 2     // 参数检查.
 3     int ret=-1;
 4     if (offset > m_nFileSize || !m_file.is_open()){
 5         LOGI("seek offset=%d> file size:%d,or file is close.",offset,m_nFileSize);
 6         return -1;
 7     }
 8     if (m_bIsMultithread)
 9         m_mutex.Lock();
10 
11     std::ios_base::seekdir way = (std::ios_base::seekdir)whence;
12     // 进行seek操作.
13     if (whence != AVSEEK_SIZE) {
14         //先把错误位置给
15         m_file.clear();
16         //////////////////////////////
17         switch(whence){
18             case SEEK_SET:
19                 //基于文件开始位置进行seek跳转
20                 m_file.seekg(offset,std::ios_base::beg);
21 //            ret = offset;
22                 break;
23             case SEEK_CUR:
24                 //基于文件当前位置进行seek跳转
25                 m_file.seekg(offset,std::ios_base::cur);
26 //            ret=m_file.tellg();
27                 break;
28             case SEEK_END:
29                 //基于文件尾的位置进行seek跳转
30                 m_file.seekg(offset,std::ios_base::end);
31 //            ret=m_file.tellg();
32                 break;
33         }
34         if (m_file.good())
35             ret = m_file.tellg();
36         else
37             ret = -1;
38     }else{
39         //等于AVSEEK_SIZE,这个主要是用于获取文件大小
40 //        The whence-parameter has one  more option than fseek: AVSEEK_SIZE.
41 // When this option is passed to the seek function it should return the file size (if possible).
42 // If its not possible, the function may return and do nothing -1. In my implementation pStream->Seek(...) will fail with AVSEEK_SIZE and SeekFunc will return -1.
43         ret=m_nFileSize;
44     }
45 
46     if (m_bIsMultithread)
47         m_mutex.Unlock();
48 
49     return ret;
50 }
然后,视频就能正常解码和播放了
 转载请注明出处:https://www.cnblogs.com/lihaiping/p/10637615.html
原文地址:https://www.cnblogs.com/lihaiping/p/10637615.html