FFMPEG+SDL2 实现播放器功能

本文详细介绍了如何利用FFMPEG和SDL2库创建一个播放器,包括界面设计、音视频读取、线程管理和音视频同步。通过分析代码和关键函数,展示了从打开文件到显示视频的整个流程。同时,提供了课程链接和源码下载,供读者深入学习和实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ffmpeg视频H264压缩,rtsp推流课程教学视频:

https://edu.youkuaiyun.com/course/detail/27795

课件中里面提供源码可以直接下载运行!

-------------------------------------------------------------------------------------------------------------------------------------

一、界面

    1 打开的pushbutton

    2 停止/开始的pushbutton

    3 进度条  QSlider

    4 播放窗口widget

二、创建videothread线程

    该线程用于读取视频数据流   具体实现过程可以参考

    http://blog.youkuaiyun.com/yunge812/article/details/79342089

    其中需要添加SDL处理音频的部分进去

   2.1 SDL初始化

if (SDL_Init(SDL_INIT_AUDIO))
    {
        fprintf(stderr,"Could not initialize SDL - %s. \n", SDL_GetError());
        exit(1);
    }

   2.2 获取音频流信息

for (i = 0; i < pFormatCtx->nb_streams; i++)
   {    
       if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO  && audioStream < 0)
       {
           audioStream = i;
       }

   }

///如果audioStream为-1 说明没有找到音频流
   if (audioStream == -1) {
       printf("Didn't find a audio stream.\n");
       return;
   }

if (audioStream >= 0)
   {
       /// 设置SDL音频流信息 音频处理初始化
       audio_stream_component_open(&mVideoState, audioStream);  //该函数后续会进行完成
   }

audio_stream_component_open函数在3.3.1中会涉及

 

 

2.3  查找音频解码器


///================================ 查找音频解码器 =================================//
   AVCodecContext *aCodecCtx;
   aCodecCtx = pFormatCtx->streams[audioStream]->codec;
   AVCodec *aCodec;
   aCodec = avcodec_find_decoder(aCodecCtx->codec_id);

   if (aCodec == NULL)
   {
       printf("ACodec not found.\n");
       return;
   }

   ///================================ 打开音频解码器 ==================================//
   if (avcodec_open2(aCodecCtx, aCodec, NULL) < 0)
   {
       printf("Could not open audio codec.\n");
       return;
   }    1 SDL初始化
   vs->audio_st = pFormatCtx->streams[audioStream]; ///设置音频解码

   packet_queue_init(&vs->videoq); //音频处理:初始化队列

 2.4 创建视频解码的线程  由SDL进行创建  video_thread函数后续阶段完成

 vs->video_tid = SDL_CreateThread(video_thread, "video_thread", &mVideoState);
 vs->player = this; //线程指针


 2.5  分配AVPacket用于存放读取的视频

 

 AVPacket *packet = (AVPacket *) malloc(sizeof(AVPacket)); //分配一个packet 用于存放读取的视频

三、开始进行音视频的读取

    3.1 音视频统一读取

 //===========================  读取视频信息 ===============================//
       if (av_read_frame(pFormatCtx, packet) < 0) //读取的是一帧视频  数据存入一个AVPacket的结构中
       {
           qDebug()  << "read error." ;
           return ;
       }
       //此时数据存储在packet中

       if (packet->stream_index == videoStream)
       {
           packet_queue_put(&vs->videoq, packet); //这里我们将视频数据存入队列

       }
       else if( packet->stream_index == audioStream )
       {
           packet_queue_put(&vs->audioq, packet);//这里我们将音频数据存入队列

       }

    3.2 视频读取线程   将视频转换成QImage显示

        3.2.1 视频相关结构体的分配

 ///解码视频相关
    AVFrame *pFrame, *pFrameRGB;
    uint8_t *out_buffer_rgb; //解码后的rgb数据
    struct SwsContext *img_convert_ctx;  //用于解码后的视频格式转换

    AVCodecContext *pCodecCtx = is->video_st->codec; //视频解码器

    pFrame = av_frame_alloc();
    pFrameRGB = av_frame_alloc();

    ///这里我们改成了 将解码后的YUV数据转换成RGB32
    img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
            pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
            PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);

    numBytes = avpicture_get_size(PIX_FMT_RGB32, pCodecCtx->width,pCodecCtx->height);

    out_buffer_rgb = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
    avpicture_fill((AVPicture *) pFrameRGB, out_buffer_rgb, PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height);
    // 会将pFrameRGB的数据按RGB格
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳光非宅男

你的鼓励是我最大的肯定

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值