GithubHelp home page GithubHelp logo

johnneycat / video_player Goto Github PK

View Code? Open in Web Editor NEW

This project forked from mushroom0709/ffmpeg_demo

0.0 1.0 0.0 138.75 MB

基于FFmpeg+SDL2 实现的视频文件播放

C 96.22% C++ 2.72% CMake 0.61% Objective-C 0.38% Makefile 0.06%

video_player's Introduction

基于FFmpeg+SDL2 实现的视频文件播放

  • 主要用于演示基于ffmepg进行解码视频文件的流程和使用方法,以及部分音视频的基础知识。
  • 自行编写了音视频同步算法

使用说明

  • 请使用VS2019打开并切换到debug & x86 下编译运行(不出意外f5即可一键启动)。

其他版本

视频演示

技术说明

  • FFmepg解码流程图 FFmepg解码流程图

  • 代码逻辑图 点击查看大图 代码逻辑图

  • 音视频同步算法

    		// 计算代表帧率控制的延迟(微秒)
      		int64_t CalDelay(double _pts)
      		{
      			int64_t i64_delay = 0; // 最终休眠时间(微秒)
      			double elapsed_time = 0.0;
    
      			if (video_show_start_time_ == 0.0)
      				SetVideoShowTime(); // 避免 0值或其他值影响第一帧播放
    
      			double diff = _pts - audio_clock_;	   //计算当前视频帧时钟与主时钟理论差值
      			double delay = _pts - last_video_pts_; //计算本帧理论上需要在上一帧多少时间之后再显示
      			int series = std::to_string(static_cast<int64_t>(diff * AV_TIME_BASE)).size();
    
      			last_video_pts_ = _pts; //记录上一帧的PTS
    
      			if (diff > X_AVSYNC_DYNAMIC_THRESHOLD)
      			{
      				// 如果 时钟差值为正数,则表示视频播放在前,则取差值的 
      				// 的((1.0 + X_AVSYNC_DYNAMIC_COEFFICIENT)^series - 1.0)倍
      				// 作为代表帧率的延时时间的修正数,即 实际延迟 = 理论延时 + 修正数;
      				diff = diff * (std::pow(1.0 + X_AVSYNC_DYNAMIC_COEFFICIENT, series) - 1.0);
      			}
      			else if (diff < -X_AVSYNC_DYNAMIC_THRESHOLD)
      			{
      				// 如果 时钟差值为负数,则表示音频播放在前,则取差值的 
      				// 的((1.0 + X_AVSYNC_DYNAMIC_COEFFICIENT)^series - 1.0)倍
      				// 作为代表帧率的延时时间的修正数,即 实际延迟 = 理论延时 - |修正数|;
      				diff = diff * (std::pow(1.0 + X_AVSYNC_DYNAMIC_COEFFICIENT, series) - 1.0);
      			}
      			// 对了,这个修正数的算法是自己拍脑袋想的,单纯的*0.1也行
    
      			if (delay > 0.0 && (delay + diff) > 0.0)
      			{
      				delay += diff;
    
      				//到显示时本周期已消耗时间 = 即将显示视频帧时间-周期起始时间
      				elapsed_time = av_gettime_relative() / AV_TIME_BASE * 1.0 - video_show_start_time_;
    
      				//最终延迟时间 = 实际延迟时间 - 已经消耗时间。并转换为微秒
      				i64_delay = static_cast<int64_t>((delay - elapsed_time) * AV_TIME_BASE);
      			}
      			else
      			{
      				// 如果理论延迟或者实际延迟为负数,则需要进行跳帧处理
      				i64_delay = X_AVSYNC_SKIP_FRAME;
      			}
    
      			printf("%lf\t%lf\n", delay, diff);
      			return i64_delay;
      		}
    
      void xPlayer::play_video_function()
      {
        xPtrFrame frame = NULL;
        int64_t delay = 0;
    
        while (run_flag_)
        {
            if (true == qvdata_.TryPop(frame))
            {
                SDL_UpdateYUVTexture(s_txture, NULL,
                    frame->data[0], frame->linesize[0],
                    frame->data[1], frame->linesize[1],
                    frame->data[2], frame->linesize[2]);
                SDL_RenderClear(s_render);
                SDL_RenderCopy(s_render, s_txture, NULL, &s_rect_);
    
                delay = av_sync_.CalDelay(frame->dpts); // 此处计算帧率(延迟)
    
                if (delay > 0)
                {
                    std::this_thread::sleep_for(std::chrono::microseconds(delay));
    
                    //std::this_thread::sleep_for(std::chrono::microseconds(delay+rand()%40000)); //用作音视频同步测试
                }
                else if (X_AVSYNC_SKIP_FRAME == delay)
                {
                    //
                }
    
                //printf("%I64d\n", delay);
    
                SDL_RenderPresent(s_render);
                av_sync_.SetVideoShowTime(); // 记录周期起始时间
    
    
                delete frame;
            }
            else
            {
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
            }
        }
      }
    

参考及答谢

吐槽

  • 下视频测试的时候使用了优酷客户端,然后自动转 码出来的视频后半截pts炸裂了,我以为是我程序 出现了BUG,调试了好久……。淦。
@xMushroom

video_player's People

Contributors

mushroom0709 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.