Invalid packet stream index

举报
风吹稻花香 发表于 2021/06/05 01:17:01 2021/06/05
【摘要】 原因: pkt->stream_index < 0 || pkt->stream_index >= s->nb_streams s是AVFormatContext  *ofmt_ctx; 1.av_write_frame() av_write_frame()用于输出一帧视音频数据,它的声明位于libavformat\avformat...

原因:

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

  
  1. 简单解释一下它的参数的含义:
  2. s:用于输出的AVFormatContext
  3. pkt:等待输出的AVPacket
  4. 函数正常执行后返回值等于0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

av_write_frame()的定义位于libavformat\mux.c,如下所示。


  
  1. int av_write_frame(AVFormatContext *s, AVPacket *pkt)
  2. {
  3. int ret;
  4. ret = check_packet(s, pkt);
  5. if (ret < 0)
  6. return ret;
  7. //PacketNULLFlush Encoder
  8. if (!pkt) {
  9. if (s->oformat->flags & AVFMT_ALLOW_FLUSH) {
  10. ret = s->oformat->write_packet(s, NULL);
  11. if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)
  12. avio_flush(s->pb);
  13. if (ret >= 0 && s->pb && s->pb->error < 0)
  14. ret = s->pb->error;
  15. return ret;
  16. }
  17. return 1;
  18. }
  19. ret = compute_pkt_fields2(s, s->streams[pkt->stream_index], pkt);
  20. if (ret < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
  21. return ret;
  22. //写入
  23. ret = write_packet(s, pkt);
  24. if (ret >= 0 && s->pb && s->pb->error < 0)
  25. ret = s->pb->error;
  26. if (ret >= 0)
  27. s->streams[pkt->stream_index]->nb_frames++;
  28. return ret;
  29. }
  • 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,如下所示。


  
  1. static int check_packet(AVFormatContext *s, AVPacket *pkt)
  2. {
  3. if (!pkt)
  4. return 0;
  5. if (pkt->stream_index < 0 || pkt->stream_index >= s->nb_streams) {
  6. av_log(s, AV_LOG_ERROR, "Invalid packet stream index: %d\n",
  7. pkt->stream_index);
  8. return AVERROR(EINVAL);
  9. }
  10. if (s->streams[pkt->stream_index]->codec->codec_type == AVMEDIA_TYPE_ATTACHMENT) {
  11. av_log(s, AV_LOG_ERROR, "Received a packet for an attachment stream.\n");
  12. return AVERROR(EINVAL);
  13. }
  14. return 0;
  15. }
  • 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,如下所示。


  
  1. int av_write_trailer(AVFormatContext *s)
  2. {
  3. int ret, i;
  4. for (;; ) {
  5. AVPacket pkt;
  6. ret = interleave_packet(s, &pkt, NULL, 1);
  7. if (ret < 0)
  8. goto fail;
  9. if (!ret)
  10. break;
  11. //写入AVPacket
  12. ret = write_packet(s, &pkt);
  13. if (ret >= 0)
  14. s->streams[pkt.stream_index]->nb_frames++;
  15. av_free_packet(&pkt);
  16. if (ret < 0)
  17. goto fail;
  18. if(s->pb && s->pb->error)
  19. goto fail;
  20. }
  21. fail:
  22. //写文件尾
  23. if (s->oformat->write_trailer)
  24. if (ret >= 0) {
  25. ret = s->oformat->write_trailer(s);
  26. } else {
  27. s->oformat->write_trailer(s);
  28. }
  29. if (s->pb)
  30. avio_flush(s->pb);
  31. if (ret == 0)
  32. ret = s->pb ? s->pb->error : 0;
  33. for (i = 0; i < s->nb_streams; i++) {
  34. av_freep(&s->streams[i]->priv_data);
  35. av_freep(&s->streams[i]->index_entries);
  36. }
  37. if (s->oformat->priv_class)
  38. av_opt_free(s->priv_data);
  39. av_freep(&s->priv_data);
  40. return ret;
  41. }
  • 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

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。