看了雷神的一些文章和解释,自己重新实现了一下相关代码的东西,做为加深。

一起在音视频领域加油咯!

// 基于FFmpeg用SDL实现一个视频播放器(.h264)
///*
AVFormatContext:统领全局的基本结构体。主要用于处理封装格式(FLV/MKV/RMVB等)。
AVIOContext:输入输出对应的结构体,用于输入输出(读写文件,RTMP协议等)。
AVStream,AVCodecContext:视音频流对应的结构体,用于视音频编解码。
AVFrame:存储非压缩的数据(视频对应RGB/YUV像素数据,音频对应PCM采样数据)
AVPacket:存储压缩数据(视频对应H.264等码流数据,音频对应AAC/MP3等码流数据)
原文链接:https://blog.csdn.net/leixiaohua1020/article/details/41181155
*/extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
#include "SDL2/SDL.h"
}class SDLHandle
{
public:SDLHandle(int w, int h) {m_rect.x = 0;m_rect.y = 0;m_rect.w = w;m_rect.h = h;SdlInit();}~SDLHandle(){if (m_pTexture){SDL_DestroyTexture(m_pTexture);}if (m_pRender){SDL_DestroyRenderer(m_pRender);}if (m_pWnd){SDL_DestroyWindow(m_pWnd);}SDL_Quit();}bool CreateSDLWindow(const char* title, Uint32 flag){m_pWnd = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, m_rect.w, m_rect.h, flag);if (!m_pWnd){printf("CreateWindows error:%s.\n", SDL_GetError());return false;}m_pRender = SDL_CreateRenderer(m_pWnd, -1, 0);if (!m_pRender){return false;}m_pTexture = SDL_CreateTexture(m_pRender, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, m_rect.w, m_rect.h);if (!m_pTexture){return false;}return true;}void UpdateTexture(AVFrame* pFrame){if (!pFrame){return;}//SDL_UpdateTexture(m_pTexture, &m_rect, pFrame->data[0], pFrame->linesize[0]);SDL_UpdateYUVTexture(m_pTexture, &m_rect, pFrame->data[0], pFrame->linesize[0], pFrame->data[1], pFrame->linesize[1], pFrame->data[2], pFrame->linesize[2]);SDL_RenderClear(m_pRender);SDL_RenderCopy(m_pRender, m_pTexture, nullptr, &m_rect);SDL_RenderPresent(m_pRender);SDL_Delay(40);}
private:bool SdlInit(){if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0){printf("sdl_init error:%s\n", SDL_GetError());return false;}return true;}
private:SDL_Renderer* m_pRender = nullptr;SDL_Window* m_pWnd = nullptr;SDL_Texture* m_pTexture = nullptr;SDL_Rect m_rect;
};int main(int argc, char* argv[])
{AVFormatContext* pFormatCtx = nullptr;AVCodecContext* pCodecCtx = nullptr;AVCodec* pCodec = nullptr;  // 解码器int iVideoIndex = 0, iRet = 0;AVFrame* pFrame = nullptr;AVFrame* pFrameYUV = nullptr;AVPacket* pPacket = nullptr;unsigned char* out_buffer = nullptr;SwsContext* pSwsCtx = nullptr;FILE* fp_yuv = nullptr;int got_picture = 0;// sdlint nScreen_w = 0, nScreen_h = 0;SDL_Window* pScreen = nullptr;      // 播放窗口SDL_Renderer* pRender = nullptr;    // 渲染器SDL_Texture* pSDLTexture = nullptr; // 纹理char filepath[] = "bigbuckbunny_480x272.h265";SDLHandle* m_pSDlHandle = nullptr;// ffmpegav_register_all();avformat_network_init();pFormatCtx = avformat_alloc_context();if (!pFormatCtx){printf("avformat_alloc_context error!\n");goto exit;}// 该函数用于打开多媒体数据并且获得一些相关的信息if (avformat_open_input(&pFormatCtx, filepath, nullptr, nullptr) < 0){printf("avformat_open_input failed!\n");goto exit;}// 该函数可以读取一部分视音频数据并且获得一些相关的信息if (avformat_find_stream_info(pFormatCtx, nullptr) < 0){printf("avformat_find_stream_info error!\n");goto exit;}iVideoIndex = -1;for (int i=0; i< pFormatCtx->nb_streams; i++){if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {iVideoIndex = i;break;}}if (iVideoIndex == -1) {printf("not find a video stream.\n");goto exit;}pCodecCtx = pFormatCtx->streams[iVideoIndex]->codec;nScreen_w = pCodecCtx->width;nScreen_h = pCodecCtx->height;pCodec = avcodec_find_decoder(pCodecCtx->codec_id);     // 查找解码器if (pCodec == nullptr){printf("avcodec_find_decode error.\n");goto exit;}if (avcodec_open2(pCodecCtx, pCodec, nullptr) < 0){printf("avcodec_open2 failed!\n");goto exit;}printf("--------------- File Information ----------------\n");av_dump_format(pFormatCtx, 0, filepath, 0);printf("-------------------------------------------------\n");// 解码准备pFrame = av_frame_alloc();pFrameYUV = av_frame_alloc();pPacket = (AVPacket*)av_malloc(sizeof(AVPacket));// 申请内存  w*h*1.5(Y:w*h U:w*h/4 V:w*h/4)out_buffer = (unsigned char*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1));av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1);pSwsCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, nullptr, nullptr, nullptr);m_pSDlHandle = new SDLHandle(pCodecCtx->width, pCodecCtx->height);if (!m_pSDlHandle->CreateSDLWindow("SDL_TEXT", SDL_WINDOW_OPENGL)){printf("CreateSDLWindow error:%s\n", SDL_GetError());goto exit;}// 解码while (av_read_frame(pFormatCtx,pPacket) >= 0){if (pPacket->stream_index == iVideoIndex)   // 视频packet{iRet = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, pPacket);if (iRet < 0){printf("avcodec_decode_video2 error!\n");goto exit;}if (got_picture){sws_scale(pSwsCtx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);m_pSDlHandle->UpdateTexture(pFrame);}}av_free_packet(pPacket);}// 解码器虽然读完了 但是还有一些帧缓存while (true){iRet = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, pPacket);if (iRet < 0){break;}if (!got_picture){break;}sws_scale(pSwsCtx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);m_pSDlHandle->UpdateTexture(pFrame);}exit:if (m_pSDlHandle){delete m_pSDlHandle;m_pSDlHandle = nullptr;}if (pSwsCtx){sws_freeContext(pSwsCtx);}if (pFrame){av_frame_free(&pFrame);}if (pFrameYUV){av_frame_free(&pFrameYUV);}if (pCodecCtx){avcodec_close(pCodecCtx);}if (pFormatCtx){avformat_close_input(&pFormatCtx);}return 0;
}

SDL,ffmpeg实现简单视频播放器相关推荐

  1. <Python>PyQt5+ffmpeg,简单视频播放器的编写(解码器:K-lite)

    更新日志: 202211251640:第一版,基本功能:视频导入,播放.暂停.播放时间显示.音量控制 视频播放器 概述:本文是利用PyQt5加上ffmpeg来编写一个具备基本功能的视频播放器(播放.暂 ...

  2. 基于 FFmpeg 的跨平台视频播放器简明教程(四):像素格式与格式转换

    系列文章目录 基于 FFmpeg 的跨平台视频播放器简明教程(一):FFMPEG + Conan 环境集成 基于 FFmpeg 的跨平台视频播放器简明教程(二):基础知识和解封装(demux) 基于 ...

  3. android 实现视频播放功能,android开发之简单视频播放器(VideoView)

    简单视频播放器的使用 一.简单使用videoView和MediaController实现播放控制 1.添加需要的权限 2.设置布局 android:id="@+id/main_video&q ...

  4. 基于QtAv及ffmpeg开发的视频播放器

    基于QtAv及ffmpeg开发的视频播放器 主要功能: 本地媒体文件播放,支持切换上一个下一个文件,暂停/恢复,快放/慢放,音量控制 全屏/取消全屏 播放列表,列表缩略图 播放进度,进度条展示缩略图 ...

  5. Opencv 简单视频播放器

    最近看了一下[1]_2011_OpenCV 2 Computer Vision Application Programming Cookbook.pdf,写了一个利用Opencv库实现的简单视频播放器 ...

  6. 基于Qt、FFMpeg的音视频播放器设计一

    前言:整个项目的源代码 https://download.csdn.net/download/hfuu1504011020/10672140 最近刚完成基于Qt.FFMpeg的音视频播放器相关C++程 ...

  7. 基于NDK、C++、FFmpeg的android视频播放器开发实战-夏曹俊-专题视频课程

    基于NDK.C++.FFmpeg的android视频播放器开发实战-1796人已学习 课程介绍         课程包含了对流媒体(拉流)的播放,演示了播放rtmp的香港卫视,支持rtsp摄像头和ht ...

  8. 视频教程-基于NDK、C++、FFmpeg的android视频播放器开发实战-Android

    基于NDK.C++.FFmpeg的android视频播放器开发实战 夏曹俊:南京捷帝科技有限公司创始人,南京大学计算机硕士毕业,有15年c++跨平台项目研发的经验,领导开发过大量的c++虚拟仿真,计算 ...

  9. android 编译 sdl,SDL编译 - Android本地视频播放器开发_Linux编程_Linux公社-Linux系统门户网站...

    在上一章  Android本地视频播放器开发--ffmpeg解码视频文件中的音频(2)[http://www.linuxidc.com/Linux/2013-06/85955p5.htm]中使用Ope ...

最新文章

  1. 决策树-特征属性选择划分
  2. 机器学习理论《统计学习方法》学习笔记:第二章 感知机
  3. 地理数据库 (geodatabase) 的架构
  4. java+boolean+属性,java – 从属性中获取int,float,boolean和string
  5. 线程安全的map_面试必问-几种线程安全的Map解析
  6. 开发 一个尴尬的角色
  7. linux常用命令和操作笔记
  8. React.js 官网入门教程 分离文件 操作无法正常显示HelloWord
  9. cannot load such file -- readline
  10. c语言硬件信息监控,zabbix通过ipmi传感器监控浪潮服务器的硬件信息
  11. Jira项目导入,被导入项目与目的系统数据类型不一致导入不成功的解决方案
  12. 输入指定答案提示正确C语言,大学C语言课件及复习答案输入输出.ppt
  13. Redhat Linux安装JDK 1.7
  14. Autodesk CAD 2023简体中文正式版
  15. python调用matlab
  16. Node.js环境搭建
  17. 视频编码中CBR和VBR的区别,CRF和CQP的区别
  18. python 摄氏度和华氏度温度转换案例
  19. ssm基于Vue的共享单车app系统
  20. 2021-2027全球及中国远红外桑拿行业研究及十四五规划分析报告

热门文章

  1. scp命令的实际操作
  2. 基于XFLR5的无人机气动分析
  3. 五项措施,如何让阿里云存储更安全?
  4. 如何解决caffe和video-caffe不能使用cudnn8编译的问题
  5. QML 地图修改插件源码(一)解决Map使用Open Street Map(OSM)无法加载在线地图的解决办法
  6. 已解决yolov5报错RuntimeError: CUDA out of memory. Tried to allocate 14.00 MiB
  7. 2023惠普战66六代笔记本重装系统,U盘重装Windows11系统
  8. 常用lr_scheduler总结
  9. 国产香蕉派CM4 计算模块(Bananapi BPI-CM4 )BSP编译与开机
  10. win10如何快速切换到桌面