• (原)关于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
  • 相关阅读:
    PB中的函数ProfileString
    PB做大屏显示滚动窗口 [转载]
    PB对象(sqlca、sqlsa、sqlda)[转载]
    SQL中 EXCEPT、INTERSECT用法[转载]
    第一篇博客
    Intelli IDEA 炫酷插件
    概念总结
    秒杀系统(四)——异常处理和常量的处理
    秒杀系统(三)——实现哪些秒杀系统功能
    秒杀系统(二)
  • 原文地址:https://www.cnblogs.com/lihaiping/p/10637615.html
Copyright © 2020-2023  润新知