当前位置: 首页>C++>正文

視頻解析網站源碼,ijkplayer源碼分析 視頻渲染流程

視頻解析網站源碼,ijkplayer源碼分析 視頻渲染流程

前言

  • 本系列如下:
    整體概述
    視頻渲染流程
    音頻播放流程
    read線程流程
    音頻解碼流程
    視頻解碼流程
    視頻向音頻同步
    start流程和buffering緩沖策略

本文是流程分析的第一篇,分析ijkPlayer中的視頻渲染流程,在video_refresh_thread中,如下流程圖中所示。
在這里插入圖片描述

SDL_Vout和SDL_VoutOverlay結構體

SDL_Vout

SDL_Vout表示一個顯示上下文,或者理解為一塊畫布,ANativeWindow,控制如何顯示overlay。

// ijksdl_aout.c
struct SDL_Vout {SDL_mutex *mutex;SDL_Class       *opaque_class;SDL_Vout_Opaque *opaque;SDL_VoutOverlay *(*create_overlay)(int width, int height, int frame_format, SDL_Vout *vout);void (*free_l)(SDL_Vout *vout);int (*display_overlay)(SDL_Vout *vout, SDL_VoutOverlay *overlay);Uint32 overlay_format;
};
  • 實現為:
    ijksdl_vout_dummy.c
    ijksdl_vout_android_nativewindow.c //在Android中使用ANativeWindow實現

SDL_VoutOverlay

視頻解析網站源碼。SDL_VoutOverlay表示顯示層,或者理解為一塊圖像數據,表達如何顯示。

struct SDL_VoutOverlay {int w; /**< Read-only */int h; /**< Read-only */Uint32 format; /**< Read-only */int planes; /**< Read-only */Uint16 *pitches; /**< in bytes, Read-only */Uint8 **pixels; /**< Read-write */int is_private;int sar_num;int sar_den;SDL_Class               *opaque_class;SDL_VoutOverlay_Opaque  *opaque;void    (*free_l)(SDL_VoutOverlay *overlay);int     (*lock)(SDL_VoutOverlay *overlay);int     (*unlock)(SDL_VoutOverlay *overlay);void    (*unref)(SDL_VoutOverlay *overlay);int     (*func_fill_frame)(SDL_VoutOverlay *overlay, const AVFrame *frame);
};
  • 實現為:
    ijksdl_vout_overlay_android_mediacodec.c
    ijksdl_vout_overlay_ffmpeg.c

調用流程

1. 通過什么方法渲染的,入口是什么

video_refresh音視頻同步后,調用video_display2()方法,從frame_queue中取出一幀后進行渲染。

static void video_image_display2(FFPlayer *ffp) {Frame *vp;vp = frame_queue_peek_last(&is->pictq); // 從frame_queue中取出一幀if (vp->bmp) {SDL_VoutDisplayYUVOverlay(ffp->vout, vp->bmp); // frame中的bmp}
}
int SDL_VoutDisplayYUVOverlay(SDL_Vout *vout, SDL_VoutOverlay *overlay)
{if (vout && overlay && vout->display_overlay)return vout->display_overlay(vout, overlay);return -1;
}

2. SDL_Vout如何賦值的

ijkPlayer_jni.c#IjkMediaPlayer_native_setup
-> ijkplayer_android.c#ijkmp_android_create
-> ijksdl_vout_android_surface.c#SDL_VoutAndroid_CreateForAndroidSurface
-> ijksdl_vout_android_nativewindow.c#SDL_VoutAndroid_CreateForANativeWindow // 創建SDL_Vout

IjkMediaPlayer *ijkmp_android_create(int(*msg_loop)(void*))
{IjkMediaPlayer *mp = ijkmp_create(msg_loop);// ...mp->ffplayer->vout = SDL_VoutAndroid_CreateForAndroidSurface();// ...
}

怎么從源代碼中提取視頻、之后通過setSurface(),創建ANativeWindow,并賦值給SDL_Vout_Opaque

3. frame中的bmp是如何賦值的

ff_ffplay.c#stream_component_open中decoder_start方法啟動video_thread開啟解碼
–> 軟解調用到ff_ffplay.c#ffplay_video_thread方法
–> 硬解調用到ffpipenode_android_mediacodec_vdec.c#func_run_sync方法
-> 最后都回調到queue_picture,將該幀放入frame_queue隊列中,等待渲染。

// 軟解,ffpipenode_ffplay_vdec.c
static int ffplay_video_thread(void *arg) {AVFrame *frame = av_frame_alloc();for(;;){ret = get_video_frame(ffp, frame); // avcodec_receive_frame軟解碼獲取一幀queue_picture(ffp, frame, pts, duration, frame->pkt_pos, is->viddec.pkt_serial);}
}// 硬解,ffpipenode_android_mediacodec_vdec.c
static int func_run_sync(IJKFF_Pipenode *node){int got_frame = 0;while (!q->abort_request) {drain_output_buffer(env, node, timeUs, &dequeue_count, frame, &got_frame);if (got_frame) {// 通過頭文件調用到queue_pictureffp_queue_picture(ffp, frame, pts, duration, av_frame_get_pkt_pos(frame), is->viddec.pkt_serial);}}
}// 入隊 ff_ffplay.c
static int
queue_picture(FFPlayer *ffp, AVFrame *src_frame, double pts, double duration, int64_t pos, int serial) {Frame *vp;vp = frame_queue_peek_writable(&is->pictq); // 獲取一個可寫節點if (!vp->bmp){alloc_picture(ffp, src_frame->format); // 創建bmpvp->allocated = 0;vp->width = src_frame->width;vp->height = src_frame->height;vp->format = src_frame->format;}if (vp->bmp) {SDL_VoutLockYUVOverlay(vp->bmp); // 鎖SDL_VoutFillFrameYUVOverlay(vp->bmp, src_frame);  // 調用func_fill_frame把幀畫面“繪制”到最終的顯示圖層上SDL_VoutUnlockYUVOverlay(vp->bmp);vp->pts = pts;vp->duration = duration;vp->pos = pos;vp->serial = serial;vp->sar = src_frame->sample_aspect_ratio;vp->bmp->sar_num = vp->sar.num;vp->bmp->sar_den = vp->sar.den;frame_queue_push(&is->pictq); // 對節點操作結束后,調用frame_queue_push告知FrameQueue“存入”該節點}}// 創建bmp
static void alloc_picture(FFPlayer *ffp, int frame_format) {vp->bmp = SDL_Vout_CreateOverlay(vp->width, vp->height,frame_format,ffp->vout);
}

// 實現如下

static SDL_VoutOverlay *
func_create_overlay_l(int width, int height, int frame_format, SDL_Vout *vout) {switch (frame_format) {case IJK_AV_PIX_FMT__ANDROID_MEDIACODEC:return SDL_VoutAMediaCodec_CreateOverlay(width, height, vout);default:return SDL_VoutFFmpeg_CreateOverlay(width, height, frame_format, vout);}
}

4. display_overlay流程

potplayer設置源碼輸出。從frame_queue中取出一幀后渲染到屏幕上,從代碼中看到,可以通過MediaCodec、EGL、ANativeWindow的方式渲染到屏幕上。
后面會具體分析相關api在Android native層的用法,是怎么渲染到屏幕上的。

// ijksdl_vout_android_nativewindow.c
static int func_display_overlay_l(SDL_Vout *vout, SDL_VoutOverlay *overlay) {
switch (overlay->format) {case SDL_FCC__AMC: {// only ANativeWindow supportIJK_EGL_terminate(opaque->egl);return SDL_VoutOverlayAMediaCodec_releaseFrame_l(overlay, NULL, true); // MediaCodec}case SDL_FCC_RV24:case SDL_FCC_I420:case SDL_FCC_I444P10LE: {// only GLES supportif (opaque->egl)return IJK_EGL_display(opaque->egl, native_window, overlay);  // EGLbreak;}case SDL_FCC_YV12:case SDL_FCC_RV16:case SDL_FCC_RV32: {// both GLES & ANativeWindow supportif (vout->overlay_format == SDL_FCC__GLES2 && opaque->egl)return IJK_EGL_display(opaque->egl, native_window, overlay);  // EGLbreak;}}// fallback to ANativeWindowIJK_EGL_terminate(opaque->egl);return SDL_Android_NativeWindow_display_l(native_window, overlay); // 渲染ARGB
}

參考:
ijkplayer video顯示分析

https://www.nshth.com/cplus/338435.html
>

相关文章:

  • 視頻解析網站源碼
  • 怎么從源代碼中提取視頻
  • potplayer設置源碼輸出
  • 視頻源代碼
  • 渲染api
  • js處理視頻流
  • 可編程渲染管線
  • 渲染輸出
  • 樹莓派的控制方法,第二篇 樹莓派基本外設基礎篇
  • 手機如何連接外設,iOS連接外設的幾種方式
  • switch可以外接鍵鼠嗎,別再給手機外接OTG鍵鼠玩刺激戰場了:其實還能這樣操作
  • [阿發你好]C/C++學習指南
  • 輸入法哪個最好用,wsl2中安裝中文輸入法
  • 字符串中引入變量方法,字符串處理、變量初始值處理、擴展的腳本技巧、正則表達式
  • 某計算機內存容量是512kb,某計算機主存容量為512kb,Cache容量為16kb,每塊有16個字,每字32位。 (1...
  • 中國工商網商標查詢,工商局爬蟲 商標網爬蟲
  • iOS真機調試TestFlight安裝及提交App Store審核教程
  • 蘋果app上架流程,小白如何在ios中安裝ios上架
  • 蘋果彈出提交表格是什么,蘋果TestFlight測試操作圖文教程(測試后提交App Store審核)
  • 四門外語傍身:外語,讓我的大學如此完美
  • D3D Surface/Texture SDL DDraw渲染視頻的區別和疑問
  • 手機VR播放器,Android VR Player(全景視頻播放器) [10]: VR全景視頻渲染播放的實現(exoplayer,glsurfaceview,o
  • Qt渲染視頻常見問題(視頻渲染窗口上子窗口設置透明出現陰影問題、主窗口縮放導致視頻渲染窗口部分出現視頻閃爍問題)
  • 視頻解析網站源碼,ijkplayer源碼分析 視頻渲染流程
  • 一分鐘的視頻渲染要多久,基礎教程|如何在數分鐘時間內渲染超清精美視頻?
  • Metal(六) 案例之視頻文件的渲染
  • flutter開發小程序,最強整理!寫給程序員的Flutter詳細教程,大廠直通車!
  • c++黑客編程揭秘與防范,C/C++截獲騰訊QQ網絡聊天系統內容和登錄密碼,教你做一個黑客!
  • 支付行業具體做什么,做支付需要了解哪些行業知識
  • 5大底層邏輯,淺談HyperLogLog底層算法邏輯
  • c++實現復數的加減乘除,【C++】輔助C++計算復數(代碼解釋的很清楚)
  • nlogn的算法有哪些,算法運行時間1、logN、N、NlogN 、N^2、N^3、2^n之間的比較
  • 開源圖片庫,幾種常用圖像處理開源庫簡介及使用總結
  • 圖像處理和計算機視覺,《圖像處理與計算機視覺算法及應用》讀后感
  • gps定位,側邊欄固定定位到版心兩側
  • css版心怎么設置,[css]版心和布局流程
  • 瀏覽器多個窗口怎么設置在一個頁面,網頁多種版心適應多屏幕技巧
  • 前端學習之版心和布局流程