Invalid packet stream index
原因:
pkt->stream_index < 0 || pkt->stream_index >= s->nb_streams
s是AVFormatContext *ofmt_ctx;
1.av_write_frame()
av_write_frame()用于输出一帧视音频数据,它的声明位于libavformat\avformat.h,如下所示。
int av_write_frame(AVFormatContext *s, AVPacket *pkt); 
 
- 1
 
  
   - 
    
     
    
    
     
      简单解释一下它的参数的含义:
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
       s:用于输出的AVFormatContext。
     
    
 
   - 
    
     
    
    
     
       pkt:等待输出的AVPacket。
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
      函数正常执行后返回值等于0。
     
    
 
  
 
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 
av_write_frame()的定义位于libavformat\mux.c,如下所示。
  
   - 
    
     
    
    
     
       int av_write_frame(AVFormatContext *s, AVPacket *pkt)  
     
    
 
   - 
    
     
    
    
     
       {  
     
    
 
   - 
    
     
    
    
     
       int ret;  
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
       ret = check_packet(s, pkt);  
     
    
 
   - 
    
     
    
    
      if (ret < 0)  
     
    
 
   - 
    
     
    
    
     
       return ret;  
     
    
 
   - 
    
     
    
    
     
       //Packet为NULL,Flush Encoder  
     
    
 
   - 
    
     
    
    
      if (!pkt) {  
     
    
 
   - 
    
     
    
    
      if (s->oformat->flags & AVFMT_ALLOW_FLUSH) {  
     
    
 
   - 
    
     
    
    
     
       ret = s->oformat->write_packet(s, NULL);  
     
    
 
   - 
    
     
    
    
      if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)  
     
    
 
   - 
    
     
    
    
     
       avio_flush(s->pb);  
     
    
 
   - 
    
     
    
    
      if (ret >= 0 && s->pb && s->pb->error < 0)  
     
    
 
   - 
    
     
    
    
     
       ret = s->pb->error;  
     
    
 
   - 
    
     
    
    
     
       return ret;  
     
    
 
   - 
    
     
    
    
     
       }  
     
    
 
   - 
    
     
    
    
     
       return 1;  
     
    
 
   - 
    
     
    
    
     
       }  
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
       ret = compute_pkt_fields2(s, s->streams[pkt->stream_index], pkt);  
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
      if (ret < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))  
     
    
 
   - 
    
     
    
    
     
       return ret;  
     
    
 
   - 
    
     
    
    
     
       //写入  
     
    
 
   - 
    
     
    
    
     
       ret = write_packet(s, pkt);  
     
    
 
   - 
    
     
    
    
      if (ret >= 0 && s->pb && s->pb->error < 0)  
     
    
 
   - 
    
     
    
    
     
       ret = s->pb->error;  
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
      if (ret >= 0)  
     
    
 
   - 
    
     
    
    
     
       s->streams[pkt->stream_index]->nb_frames++;  
     
    
 
   - 
    
     
    
    
     
       return ret;  
     
    
 
   - 
    
     
    
    
     
       }  
     
    
 
  
 
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 - 28
 - 29
 - 30
 - 31
 - 32
 - 33
 
从源代码可以看出,av_write_frame()主要完成了以下几步工作: 
(1)调用check_packet()做一些简单的检测 
(2)调用compute_pkt_fields2()设置AVPacket的一些属性值 
(3)调用write_packet()写入数据
下面分别看一下这几个函数功能。 
check_packet() 
check_packet()定义位于libavformat\mux.c,如下所示。
  
   - 
    
     
    
    
     
       static int check_packet(AVFormatContext *s, AVPacket *pkt)  
     
    
 
   - 
    
     
    
    
     
       {  
     
    
 
   - 
    
     
    
    
      if (!pkt)  
     
    
 
   - 
    
     
    
    
     
       return 0;  
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
      if (pkt->stream_index < 0 || pkt->stream_index >= s->nb_streams) {  
     
    
 
   - 
    
     
    
    
     
       av_log(s, AV_LOG_ERROR, "Invalid packet stream index: %d\n",  
     
    
 
   - 
    
     
    
    
     
       pkt->stream_index);  
     
    
 
   - 
    
     
    
    
     
       return AVERROR(EINVAL);  
     
    
 
   - 
    
     
    
    
     
       }  
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
      if (s->streams[pkt->stream_index]->codec->codec_type == AVMEDIA_TYPE_ATTACHMENT) {  
     
    
 
   - 
    
     
    
    
     
       av_log(s, AV_LOG_ERROR, "Received a packet for an attachment stream.\n");  
     
    
 
   - 
    
     
    
    
     
       return AVERROR(EINVAL);  
     
    
 
   - 
    
     
    
    
     
       }  
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
       return 0;  
     
    
 
   - 
    
     
    
    
     
       }  
     
    
 
  
 
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 
从代码中可以看出,check_packet()的功能比较简单:首先检查一下输入的AVPacket是否为空,如果为空,则是直接返回;然后检查一下AVPacket的stream_index(标记了该AVPacket所属的AVStream)设置是否正常,如果为负数或者大于AVStream的个数,则返回错误信息;
compute_pkt_fields2() 
compute_pkt_fields2()主要有两方面的功能:一方面用于计算AVPacket的duration, dts等信息;另一方面用于检查pts、dts这些参数的合理性(例如PTS是否一定大于DTS)
AVOutputFormat->write_packet() 
write_packet()函数最关键的地方就是调用了AVOutputFormat中写入数据的方法。如果AVPacket中的flag标记中包含AV_PKT_FLAG_UNCODED_FRAME,就会调用AVOutputFormat的write_uncoded_frame()函数;如果不包含那个标记,就会调用write_packet()函数。write_packet()实际上是一个函数指针,指向特定的AVOutputFormat中的实现函数。
2.av_write_trailer()
av_write_trailer()用于输出文件尾,它的声明位于libavformat\avformat.h,如下所示。
int av_write_trailer(AVFormatContext *s);  
 
- 1
 
它只需要指定一个参数,即用于输出的AVFormatContext。 
函数正常执行后返回值等于0。 
av_write_trailer()的定义位于libavformat\mux.c,如下所示。
  
   - 
    
     
    
    
     
       int av_write_trailer(AVFormatContext *s)  
     
    
 
   - 
    
     
    
    
     
       {  
     
    
 
   - 
    
     
    
    
     
       int ret, i;  
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
       for (;; ) {  
     
    
 
   - 
    
     
    
    
      AVPacket pkt;  
     
    
 
   - 
    
     
    
    
     
       ret = interleave_packet(s, &pkt, NULL, 1);  
     
    
 
   - 
    
     
    
    
      if (ret < 0)  
     
    
 
   - 
    
     
    
    
     
       goto fail;  
     
    
 
   - 
    
     
    
    
      if (!ret)  
     
    
 
   - 
    
     
    
    
     
       break;  
     
    
 
   - 
    
     
    
    
     
       //写入AVPacket  
     
    
 
   - 
    
     
    
    
     
       ret = write_packet(s, &pkt);  
     
    
 
   - 
    
     
    
    
      if (ret >= 0)  
     
    
 
   - 
    
     
    
    
     
       s->streams[pkt.stream_index]->nb_frames++;  
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
       av_free_packet(&pkt);  
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
      if (ret < 0)  
     
    
 
   - 
    
     
    
    
     
       goto fail;  
     
    
 
   - 
    
     
    
    
      if(s->pb && s->pb->error)  
     
    
 
   - 
    
     
    
    
     
       goto fail;  
     
    
 
   - 
    
     
    
    
     
       }  
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
     
       fail:  
     
    
 
   - 
    
     
    
    
     
       //写文件尾  
     
    
 
   - 
    
     
    
    
      if (s->oformat->write_trailer)  
     
    
 
   - 
    
     
    
    
      if (ret >= 0) {  
     
    
 
   - 
    
     
    
    
     
       ret = s->oformat->write_trailer(s);  
     
    
 
   - 
    
     
    
    
     
       } else {  
     
    
 
   - 
    
     
    
    
     
       s->oformat->write_trailer(s);  
     
    
 
   - 
    
     
    
    
     
       }  
     
    
 
   - 
    
     
    
    
      
     
    
 
   - 
    
     
    
    
      if (s->pb)  
     
    
 
   - 
    
     
    
    
     
       avio_flush(s->pb);  
     
    
 
   - 
    
     
    
    
      if (ret == 0)  
     
    
 
   - 
    
     
    
    
     
       ret = s->pb ? s->pb->error : 0;  
     
    
 
   - 
    
     
    
    
     
       for (i = 0; i < s->nb_streams; i++) {  
     
    
 
   - 
    
     
    
    
     
       av_freep(&s->streams[i]->priv_data);  
     
    
 
   - 
    
     
    
    
     
       av_freep(&s->streams[i]->index_entries);  
     
    
 
   - 
    
     
    
    
     
       }  
     
    
 
   - 
    
     
    
    
      if (s->oformat->priv_class)  
     
    
 
   - 
    
     
    
    
     
       av_opt_free(s->priv_data);  
     
    
 
   - 
    
     
    
    
     
       av_freep(&s->priv_data);  
     
    
 
   - 
    
     
    
    
     
       return ret;  
     
    
 
   - 
    
     
    
    
     
       }  
     
    
 
  
 
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 - 28
 - 29
 - 30
 - 31
 - 32
 - 33
 - 34
 - 35
 - 36
 - 37
 - 38
 - 39
 - 40
 - 41
 - 42
 - 43
 - 44
 - 45
 - 46
 
从源代码可以看出av_write_trailer()主要完成了以下两步工作:
(1)循环调用interleave_packet()以及write_packet(),将还未输出的AVPacket输出出来。
(2)调用AVOutputFormat的write_trailer(),输出文件尾。
AVOutputFormat->write_trailer() 
AVOutputFormat的write_trailer()是一个函数指针,指向特定的AVOutputFormat中的实现函数。
文章来源: blog.csdn.net,作者:网奇,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/jacke121/article/details/80298184
- 点赞
 - 收藏
 - 关注作者
 
            
           
评论(0)