avformat_find_stream_info获取视频流信息

在一些格式信息中可能没有头部信息,比如:FLV 可以用avformat_find_stream_info探测文件信息:编码宽高,但不能获取总时长。
image.png

尝试打印视频时长和流信息:可以发现FLV 里面是没有读到的

image.png

尝试添加 avformat_find_stream_info

  //获取流信息 读取部分视频做探测
    avformat_open_input_result = avformat_find_stream_info(avformat_context, 0);
    if (avformat_open_input_result != 0) {
        NSLog(@"avformat_find_stream_info failed!");
    }

image.png
读取成功,如果有些文件读取不出时长,用遍历帧的方式计算时长

av_find_best_stream()

    // ====================================
    /**
     获取音视频流的索引

     @param ic#> 上下文 description#>
     @param type#> 音频/视频流信息类型 description#>
     @param wanted_stream_nb#> 指定取的流的信息(传 -1) description#>
     @param related_stream#> 想关流信息(-1) description#>
     @param decoder_ret#> 解码器 (NULL) description#>
     @param flags#> 暂时无用 description#>
     @return <#return value description#>
     */
    audioStream = av_find_best_stream(avformat_context, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
    NSLog(@" av_find_best_stream : %d ",audioStream);

    //关闭输入的上下文 释放内存
    avformat_close_input(&avformat_context);

av_read_frame AVPacket AVPacket flags

AVPacket 结构体
• AVBufferRef *buf 指针指向buf空间 存储引用计数
• int64_t pts // pts * (num/den) 显示时间
• int64_t dts 解码时间(没有B帧的话和pts是一致的)
• uint8_t *data  int size
• int stream_index
• int flags //关键帧

方法
av_packet_allc(void) 创建并初始化 内存自己管理
av_packet_clone(const AVPacket *src)创建对象,对象指向的空间的引用计数+1
int av_packet_ref 引用计数+1 av_packet_unref 引用计数 -1
void av_packet_free (AVPacket **pkt)情况对象并引用计数 -1
void av_init_packet(AVPacket **pkt) 初始化
int av_packet_from_data(AVPackt *pkt,uint8_t *data,ini size);把数据转为AVPackt 包

av_seek_frame

• int av_seek_frame(AVFormatContext *s 上下文
• int stream_index, //-1 default(视频) 索引
• int64_t timestamp, //AVStream.time_base 移动到哪个时间位置
• int flags); 标识位,移动的方法
一般选择视频来移,因为视频存在B帧的概念,音频没有,视频移都要一道关键帧的位置

• #define AVSEEK_FLAG_BACKWARD 1 ///< seek backward
• #define AVSEEK_FLAG_BYTE 2 ///< seeking based on position in bytes
• #define AVSEEK_FLAG_ANY 4 ///< seek to any frame, even non-keyframes
• #define AVSEEK_FLAG_FRAME 8 ///< seeking based on frame number
一般往后找 找到关键帧(当前时间以前叫往后)
• AVSEEK_FLAG_FRAME|AVSEEK_FLAG_BACKWARD

 //读取帧数据
    AVPacket *pkt = av_packet_alloc();//创建一个对象空间,初始化
    for (; ; ) {//无线循环
        int re = av_read_frame(ic, pkt);
        if (re != 0) {
            NSLog(@"读取到结尾处!");
            int pos = 3 * r2d(ic->streams[videoStream]->time_base);;
            av_seek_frame(ic, videoStream, pos, AVSEEK_FLAG_BACKWARD|AVSEEK_FLAG_FRAME);
            continue;
        }
        NSLog(@"stream = %d size = %d pts = %lld flag = %d",pkt->stream_index,
              pkt->size,pkt->pts,pkt->flags);
        /////操作


        av_packet_unref(pkt);
    }

猜你喜欢

转载自blog.csdn.net/u010141160/article/details/81563742