RV1126解码—ffmpeg_read_thread线程的解说

[复制链接]
发表于 2025-10-28 00:59:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
fmpeg_read_thread线程的用处
        解码这一块,在第一篇的时间就看到了,有三个线程,这篇先先容一个线程的作用是怎么样的。
        ffmpeg_read_thread线程的重要作用是读取每一帧流媒体文件,这个流媒体文件可以是复合流文件。如:TS文件、MP4文件等等,也可以包罗网络流媒体文件:如RTMP、RTSP等等。然后抽取每一帧视频帧插入到队列内里。以是就是作用就是读取每一帧视频帧入队。

         下面代码要看一下。
        第一步:avformat_open_input() 打开输入的流媒体文件
  1. #define LOCAL_TS "test_local.ts" //本地文件地址./ymx,也可以是网络地址例如:rtsp://172.0.0.1:8554/rtsp1
  2. //读取每一帧流文件,然后抽取每一帧视频帧插入到队列里面
  3. void* ffmpeg_read_thread(void* args)
  4. {
  5.     int ret;
  6.     //线程分离
  7.     pthread_detach(pthread_self());
  8.     //定义出一个大管家
  9.     AVFormatContext* ctx = nullptr;
  10.     //该函数用于打开多媒体数据并且获得一些相关的信息
  11.     ret = avformat_open_input(&ctx, LOCAL_TS, 0, 0);
  12.     if(ret < 0)
  13.     {
  14.         printf("复合文件或者网络文件打开失败\n");
  15.         return 0;
  16.     }
  17.     printf("==> 流媒体文件输入成功!\n");
  18.    
  19.    
  20. }
复制代码
        第二步:avformat_find_stream_info() :可以利用avformat_find_stream_info()获取更多的码流信息。好比获取视频帧率、视频宽高,重新盘算最大分析时长,打开解码器解码获取codec数据。
  1. #define LOCAL_TS "test_local.ts" //本地文件地址./ymx,也可以是网络地址例如:rtsp://172.0.0.1:8554/rtsp1
  2. //读取每一帧流文件,然后抽取每一帧视频帧插入到队列里面
  3. void* ffmpeg_read_thread(void* args)
  4. {
  5.     int ret;
  6.     //线程分离
  7.     pthread_detach(pthread_self());
  8.     //定义出一个大管家
  9.     AVFormatContext* ctx = nullptr;
  10.     //该函数用于打开多媒体数据并且获得一些相关的信息
  11.     ret = avformat_open_input(&ctx, LOCAL_TS, 0, 0);
  12.     if(ret < 0)
  13.     {
  14.         printf("复合文件或者网络文件打开失败\n");
  15.         return 0;
  16.     }
  17.     printf("==> 流媒体文件输入成功!\n");
  18.     // 可以使用avformat_find_stream_info()获取更多的码流信息。比如获取视频帧率、视频宽高,重新计算最大分析时长,打开解码器解码获取codec数据
  19.     avformat_find_stream_info(m_pInFmtCtx, nullptr);
  20.     printf("===========Input Information==========\n");
  21.   // 通过av_find_best_stream()函数来获取流的索引 “AVMEDIA_TYPE_VIDEO”找视频的索引
  22.     int nVideo_indx = av_find_best_stream(m_pInFmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
  23.     if (nVideo_indx < 0)
  24.     {
  25.       //todo......
  26.     }
  27.     printf("==> av_find_best_stream!\n");
  28.    
  29.    
  30. }
复制代码
        第一步和第二步就相称于初始化工作已经完成了,接下来就是这个线程最告急的一个函数“av_read_frame()”,
        先来说一下这个“av_read_frame()”,函数的一些底层的逻辑,看看是怎么工作的,
        假设下图是H264的一个连续的视频码流,视频源源不停通摄像头那里传输过来,除非克制。

         假设我把这些连续的码流团体塞给解码器,和下图一样,加密器能否正常分析出来,由于这些码流终极都要送到解码器内里分析的,但是,一下子全部给它能否工作?答案是不可的,在解码器内里是没有办法分析一个团体的数据,团体的数据就是左边的这个东西。由于解码器没有办法提取每一帧数据。

        以是我们要想它解码器能正常工作,我们要在码流中提取一帧一帧数据,送到解码器这里,那怎么提取,就是与“00 00 00 01”为切割符,是一帧数据的起始符。

        以是这也也就是av_read_frame的作用,就是提取视频里中的每一帧数据,这个时间解码器就可以工作了。
av_read_frame:这个API的具体作用是读取码流中提取一帧完备的视频帧大概音频帧。对于编解码器来说,开辟者必要获取一帧完备的数据帧才可以或许对其举行数据的编解码
  1. #define LOCAL_TS "test_local.ts" //本地文件地址./ymx,也可以是网络地址例如:rtsp://172.0.0.1:8554/rtsp1
  2. //读取每一帧流文件,然后抽取每一帧视频帧插入到队列里面
  3. void* ffmpeg_read_thread(void* args)
  4. {
  5.     int ret;
  6.     //线程分离
  7.     pthread_detach(pthread_self());
  8.     //定义出一个大管家
  9.     AVFormatContext* ctx = nullptr;
  10.     //该函数用于打开多媒体数据并且获得一些相关的信息
  11.     ret = avformat_open_input(&ctx, LOCAL_TS, 0, 0);
  12.     if(ret < 0)
  13.     {
  14.         printf("复合文件或者网络文件打开失败\n");
  15.         return 0;
  16.     }
  17.     printf("==> 流媒体文件输入成功!\n");
  18.     // 可以使用avformat_find_stream_info()获取更多的码流信息。比如获取视频帧率、视频宽高,重新计算最大分析时长,打开解码器解码获取codec数据
  19.     avformat_find_stream_info(m_pInFmtCtx, nullptr);
  20.     printf("===========Input Information==========\n");
  21.   // 通过av_find_best_stream()函数来获取流的索引 “AVMEDIA_TYPE_VIDEO”找视频的索引
  22.     int nVideo_indx = av_find_best_stream(m_pInFmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
  23.     if (nVideo_indx < 0)
  24.     {
  25.       //todo......
  26.     }
  27.     printf("==> av_find_best_stream!\n");
  28.     AVPacket *packet = av_packet_alloc();
  29.     // 通过av_read_frame获取每一帧视频帧
  30.     while (av_read_frame(m_pInFmtCtx, packet) >= 0)
  31.     {
  32.       if (packet->stream_index == nVideo_indx)//找到这个索引看看是视频的还是音频
  33.       {
  34.         video_data_packet_t *video_data_packet = (video_data_packet_t
  35.   *)malloc(sizeof(video_data_packet_t));
  36.         memcpy(video_data_packet->buffer, packet->data, packet->size);
  37.         video_data_packet->video_frame_size = packet->size;
  38.         //入队
  39.         video_queue->putVideoPacketQueue(video_data_packet);
  40.     }
  41.   }
  42.   return NULL;
  43.    
  44.    
  45. }
复制代码
         
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表