当前位置: 首页 > wzjs >正文

呼和浩特城乡建设网站网站开发培训视频

呼和浩特城乡建设网站,网站开发培训视频,中山市建设局安全监督站网站,移动网站建设书FFmpeg入门:最简单的视频播放器 FFmpeg入门第一篇,制作一个简单的MP4视频播放器。 整体流程 话不多说,直接上流程图 视频播放速率控制 这里可以直接看图中的帧率同步模块,可以分为如下几步 获取到当前帧的预期播放时间&…

FFmpeg入门:最简单的视频播放器

FFmpeg入门第一篇,制作一个简单的MP4视频播放器。

整体流程

话不多说,直接上流程图在这里插入图片描述

视频播放速率控制

这里可以直接看图中的帧率同步模块,可以分为如下几步

  1. 获取到当前帧的预期播放时间:根据时间基time_base和帧pts计算;time_base*pts
  2. 解码渲染过程中,获取当前时间av_gettime,计算和预期播放时间的时间差
  3. 使用SDL_Delay函数延迟播放时间差。

源代码

tutorial01.h

//
//  tutorial02.h
//  tutorial02
//
//  Created by chenhuaiyi on 2025/2/13.
//#ifndef tutorial02_h
#define tutorial02_h#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <libavutil/time.h>#include <SDL.h>
#include <SDL_thread.h>#include <stdio.h>/**宏定义*/
#define SFM_REFRESH_EVENT (SDL_USEREVENT+1)/**全局变量*/
extern int            thread_exit;/**方法声明*/
char* get_frame_type(AVFrame* frame);#endif /* tutorial02_h */

tutorial02.c

// tutorial02.c
// A pedagogical video player that will stream through every video frame as fast as it can.#ifdef __MINGW32__
#undef main /* Prevents SDL from overriding main() */
#endif#include "tutorial02.h"// 控制程序是否结束
int		thread_exit=0;/**获取帧类型*/
char* get_frame_type(AVFrame* frame) {switch (frame->pict_type) {case AV_PICTURE_TYPE_I:return "I";break;case AV_PICTURE_TYPE_P:return "P";break;case AV_PICTURE_TYPE_B:return "B";break;case AV_PICTURE_TYPE_S:return "S";break;case AV_PICTURE_TYPE_SI:return "SI";break;case AV_PICTURE_TYPE_SP:return "SP";break;case AV_PICTURE_TYPE_BI:return "BI";break;default:return "N";break;}
}int main(int argc, char *argv[]) {AVFormatContext*  pFormatCtx = NULL;int               i, videoStream;AVCodecContext*   pCodecCtx = avcodec_alloc_context3(NULL);;AVCodecParameters*  pCodecParam = NULL;const AVCodec*    pCodec = NULL;AVFrame*          pFrame = NULL;AVFrame*          pFrame2 = NULL;AVPacket          packet;AVDictionary*     optionsDict = NULL;struct SwsContext*  sws_ctx = NULL;SDL_Window*       window = NULL;SDL_Renderer*     renderer = NULL;SDL_Texture*      texture=NULL;SDL_Rect          rect;SDL_Event         event;if(argc < 2) {fprintf(stderr, "Usage: test <file>\n");exit(1);}// SDL组件创建if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());exit(1);}// 1. 打开视频文件,获取格式上下文if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)!=0)return -1; // Couldn't open file// 2. 对文件探测流信息if(avformat_find_stream_info(pFormatCtx, NULL)<0)return -1; // Couldn't find stream information// 打印信息av_dump_format(pFormatCtx, 0, argv[1], 0);// 3.找到对应的视频流videoStream=-1;for(i=0; i<pFormatCtx->nb_streams; i++)if(pFormatCtx->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {videoStream=i;break;}if(videoStream==-1){return -1; // Didn't find a video stream}// 4. 将视频流编码参数写入上下文pCodecParam = pFormatCtx->streams[videoStream]->codecpar;avcodec_parameters_to_context(pCodecCtx, pCodecParam);// 5. 查找流的编码器pCodec=avcodec_find_decoder(pCodecCtx->codec_id);if(pCodec==NULL) {fprintf(stderr, "Unsupported codec!\n");return -1; // Codec not found}// 6. 打开流的编解码器if(avcodec_open2(pCodecCtx, pCodec, &optionsDict)<0)return -1; // Could not open codec// 7.申请缩放颜色空间格式的上下文sws_ctx =sws_getContext(pCodecCtx->width,pCodecCtx->height,pCodecCtx->pix_fmt,pCodecCtx->width,pCodecCtx->height,AV_PIX_FMT_YUV420P,SWS_BILINEAR,NULL,NULL,NULL);// 8.帧分配pFrame=av_frame_alloc();pFrame2=av_frame_alloc();// 9.计算并分配frame帧所占内存空间int numBytes=av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1);uint8_t* buffer=(uint8_t*)av_malloc(numBytes*sizeof(uint8_t));av_image_fill_arrays(pFrame2->data, pFrame2->linesize, buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1);i=0;Uint32 start_time = SDL_GetTicks();// SDL2的最新创建和渲染窗口方式window = SDL_CreateWindow("SDL2 window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, pCodecCtx->width, pCodecCtx->height, SDL_WINDOW_SHOWN);if (!window) {printf("SDL_CreateWindow Error: %s\n", SDL_GetError());SDL_Quit();return 1;}renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);if (!renderer) {printf("SDL_CreateRenderer Error: %s\n", SDL_GetError());SDL_DestroyWindow(window);SDL_Quit();return 1;}texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, pCodecCtx->width, pCodecCtx->height);AVRational time_base = pFormatCtx->streams[videoStream]->time_base;int64_t av_start_time = av_gettime();								// 播放开始时间int64_t frame_delay = av_q2d(time_base) * AV_TIME_BASE;				// pts单位(ms*1000)int64_t frame_start_time = av_gettime();// 循环一:对文件上下文持续读取packetwhile(av_read_frame(pFormatCtx, &packet)>=0) {if(packet.stream_index==videoStream) {// 将packet写入编解码器int ret = avcodec_send_packet(pCodecCtx, &packet);if (ret < 0) {printf("packet resolve error!");break;}// 循环二:从解码器中不断读取帧while(!avcodec_receive_frame(pCodecCtx, pFrame)) { // 解码得到数据frame// 帧格式转化,转为YUV420Psws_scale(sws_ctx,(uint8_t const * const *)pFrame->data,pFrame->linesize,0,pCodecCtx->height,pFrame2->data,pFrame2->linesize);// 将AVFrame的数据写入到texture中,然后渲染后windows上rect.x = 0;rect.y = 0;rect.w = pCodecCtx->width;rect.h = pCodecCtx->height;// 更新纹理SDL_UpdateYUVTexture(texture, &rect,pFrame2->data[0], pFrame2->linesize[0],	// 	YpFrame2->data[1], pFrame2->linesize[1],	// 	UpFrame2->data[2], pFrame2->linesize[2]);	//  V// 渲染页面SDL_RenderClear(renderer);SDL_RenderCopy(renderer, texture, NULL, NULL);SDL_RenderPresent(renderer);int64_t pts = pFrame->pts;											// ptsint64_t actual_playback_time = av_start_time + pts * frame_delay;	// 实际播放时间int64_t current_time = av_gettime();if (actual_playback_time > current_time) {SDL_Delay((Uint32)(actual_playback_time-current_time)/1000);	// 延迟当前时间和实际播放时间}i++;printf("第%i帧 | 属于%s | pts为%d | 时长为%.2fms | 实际播放点为%.2fs | 预期播放点为%.2fs\n ",i,get_frame_type(pFrame),(int)pFrame->pts,(double)(av_gettime() - frame_start_time)/1000,(double)(av_gettime() - av_start_time)/AV_TIME_BASE,pFrame->pts * av_q2d(time_base));frame_start_time = av_gettime();}}// Free the packet that was allocated by av_read_frameav_packet_unref(&packet);SDL_PollEvent(&event);switch(event.type) {case SDL_QUIT:SDL_Quit();exit(0);break;default:break;}}Uint32 endTime = SDL_GetTicks();/**打印一些关键参数*/printf("格式: %s\n", pFormatCtx->iformat->name);printf("时长: %lld us\n", pFormatCtx->duration);printf("编码器: %s (%s)\n", pCodec->name, avcodec_get_name(pCodecCtx->codec_id));printf("分辨率: %dx%d\n", pCodecCtx->width, pCodecCtx->height);printf("帧率: %.2f\n", av_q2d(pFormatCtx->streams[videoStream]->avg_frame_rate));printf("帧数: %lld\n", pFormatCtx->streams[videoStream]->nb_frames);printf("比特率: %lld\n", pFormatCtx->bit_rate);printf("pts单位(ms*1000): %.2f\n", av_q2d(pFormatCtx->streams[videoStream]->time_base) * AV_TIME_BASE);printf("视频持续时长为 %d,视频帧总数为 %d\n", (endTime-start_time)/1000, i);// Free the YUV frameav_free(pFrame);av_free(pFrame2);// Close the codec paramavcodec_parameters_free(&pCodecParam);// Close the codecavcodec_free_context(&pCodecCtx);// Close the video fileavformat_close_input(&pFormatCtx);return 0;
}

文章最后,感谢音视频领域的大神@雷霄骅,雷神永垂不朽!!!


文章转载自:

http://B1xLUmqV.fnLnp.cn
http://s7ZnnJ03.fnLnp.cn
http://jpde94nK.fnLnp.cn
http://0C3mqCn2.fnLnp.cn
http://7iw5OYly.fnLnp.cn
http://PWvQLgjg.fnLnp.cn
http://9SozOHAc.fnLnp.cn
http://ZavnTvSa.fnLnp.cn
http://F1mEjpmH.fnLnp.cn
http://GqpL0fhO.fnLnp.cn
http://2jWdZaMu.fnLnp.cn
http://E5gO0B1j.fnLnp.cn
http://w4Npvsjq.fnLnp.cn
http://C93R0RE1.fnLnp.cn
http://sSNB7gEW.fnLnp.cn
http://GOTzunHe.fnLnp.cn
http://9Nf5UQ1f.fnLnp.cn
http://cX5HhGZF.fnLnp.cn
http://gI6bIZbz.fnLnp.cn
http://J2gLmME3.fnLnp.cn
http://uHeYLv6D.fnLnp.cn
http://vdbqklLT.fnLnp.cn
http://0GckmjgX.fnLnp.cn
http://Bq0nyQOJ.fnLnp.cn
http://Xm3FtxbM.fnLnp.cn
http://VAq7AGSk.fnLnp.cn
http://EJJzal3O.fnLnp.cn
http://UkwHgaFR.fnLnp.cn
http://zACLgBTt.fnLnp.cn
http://eYGolHMn.fnLnp.cn
http://www.dtcms.com/wzjs/748701.html

相关文章:

  • 东莞商城网站建设建立外贸网站
  • 网站备案一次就可以了吧长沙仿站定制模板建站
  • 网站建设300做预售的网站
  • 自建个网站怎么做网络营销工作
  • 潍坊网站建设方案书摄影师作品网站有哪些
  • 深圳外贸网站外贸网站建设中国建造师人才网官网
  • 张家口网站建设郑州网站策划
  • 网站建设具体项目及价格网络广告营销的案例
  • 延庆网站制作企业智能网站后台管理系统
  • 页面设计排版网站最新新闻资讯
  • 网站组建修改wordpress 字体
  • 电子科技学校网站建设怎样制作一个自己的网页呢
  • 网站建设熊掌号里属于什么领域嘉兴网站建设推荐浙江华企
  • 如何自己做视频网站网站友链怎么添加
  • 页面在线设计网站五八精准恶意点击软件
  • 做公司网站应准备什么材料制作一个网站费用
  • 建设网站运营方案同性男做的视频网站
  • 成都小程序定制开发seo外贸公司推广
  • 做网站要钱的吗软文的本质是什么
  • 永春网站设计网络app开发网站建设价格
  • 海口网站开发制作洛阳网站建设建站系统
  • 二手域名做网站不收录网站设计需要哪些
  • 网站怎么做数据备份山西住房与城乡建设厅定额网站
  • 设计logo网站免自己弄公司网站
  • 淘宝做基础销量网站化妆品品牌网站如何做
  • 网站建设需要的设备wordpress 网页位置
  • 铜陵做网站的顺德乐从有做阿里巴巴的网站吗
  • 涿州做网站公司微信公众平台开发者
  • 怎么申请做网站做盗版小说网站怎么样
  • 网站设网页设计wordpress 分类列表页