最も単純なFFMPEG + SDLベースのビデオプレーヤー:スプリットデコーダーとプレーヤー



Simplest Ffmpeg Sdl Based Video Player



================================================= = ==

FFmpegベースのビデオプレーヤーシリーズの最も単純なリスト:



最も単純なFFMPEG + SDLベースのビデオプレーヤー(SDL1.x)を実現するための100行のコード

最も単純なFFMPEG + SDLベースのビデオプレーヤーver2(SDL2.0を使用)



最も単純なFFmpegベースのデコーダー-純粋なバージョン(libavformatは含まれていません)

最も単純なFFMPEG + SDLベースのビデオプレーヤー:スプリットデコーダーとプレーヤー

最も単純なFFMPEGベースのHelloworldプログラム



================================================= = ==


この記事は、「シンプルなFFMPEG + SDLベースのビデオプレーヤー」の2つの例、FFmpegビデオデコーダーとSDLピクセルデータプレーヤーを補足するものです。これらの2つの部分は、ビデオプレーヤーから分割された2つの例です。 FFmpegビデオデコーダーはビデオデータのYUVデータへのデコードを実装し、SDLピクセルデータプレーヤーはYUVデータの表示を実装します。つまり、元のFFmpeg + SDLビデオプレーヤーは次のように実装されています。

ビデオデータ-> YUV->ディスプレイ

FFmpegビデオデコーダーは以下を実装します:

ビデオデータ-> YUV

SDLピクセルデータプレーヤーは以下を実装します。

YUV->ディスプレイ

FFmpegビデオデコーダー

ソースコード

[cpp] プレーンビュー コピー
  1. / **
  2. *最も単純なFFmpegベースのビデオデコーダー
  3. * SimplestFFmpegDecoder
  4. *
  5. *サンダーレイシャオワ
  6. * root @ xxxxx
  7. *中国伝媒大学/デジタルTVテクノロジー
  8. * CommunicationUniversityofChina / DigitalTVTechnology
  9. * http://blog.csdn.net/leixiaohua1020
  10. *
  11. *
  12. *このプログラムは、ビデオファイルのYUVデータへのデコードを実装します。 libavcodecを使用し、
  13. * libavformat。これはFFmpegビデオデコードに関する最も簡単なチュートリアルです。
  14. *この例を学ぶことで、FFmpegのデコードプロセスを理解することができます。
  15. *このソフトウェアはFFmpegに基づく最も単純なデコーダーです。
  16. *ビデオをYUVpixeldataにデコードします。
  17. * Ituseslibavcodecandlibavformat。
  18. * FFmpegの初心者に適しています。
  19. *
  20. * /
  21. #include
  22. #define__STDC_CONSTANT_MACROS
  23. #ifdef_WIN32
  24. //ウィンドウズ
  25. 外部「C」
  26. {{
  27. #include'libavcodec / avcodec.h '
  28. #include'libavformat / avformat.h '
  29. #include'libswscale / swscale.h '
  30. #include'libavutil / imgutils.h '
  31. }
  32. #そうしないと
  33. // Linux .. ..
  34. #ifdef__cplusplus
  35. 外部「C」
  36. {{
  37. #endif
  38. #include
  39. #include
  40. #include
  41. #include
  42. #ifdef__cplusplus
  43. }
  44. #endif
  45. #endif
  46. intメイン(intargc、char* argv [])
  47. {{
  48. AVFormatContext * pFormatCtx
  49. inti、videoindex
  50. AVCodecContext * pCodecCtx
  51. AVCodec * pCodec
  52. AVFrame * pFrame、* pFrameYUV
  53. 署名なしchar* out_buffer
  54. AVPacket * packet
  55. inty_size
  56. intret、got_picture
  57. 構造体SwsContext * img_convert_ctx
  58. charfilepath [] ='Titanic.mkv'
  59. ファイル* fp_yuv = fopen('output.yuv''wb +')。
  60. av_register_all()
  61. avformat_network_init()
  62. pFormatCtx = avformat_alloc_context()
  63. もし(avformat_open_input(&pFormatCtx、filepath、NULL、NULL)!= 0){
  64. printf('inputstreamを開くことができませんでした。 n')。
  65. 戻る-1
  66. }
  67. もし(avformat_find_stream_info(pFormatCtx、NULL)<0){
  68. printf('ストリーム情報が見つかりませんでした。 n')。
  69. 戻る-1
  70. }
  71. videoindex = -1
  72. ために(i = 0inb_streamsi ++)
  73. もし(pFormatCtx-> streams [i]-> codec-> codec_type == AVMEDIA_TYPE_VIDEO){
  74. videoindex = i
  75. ブレーク
  76. }
  77. もし(videoindex ==-1){
  78. printf(「ビデオストリームを見つけられませんでした。 n」)。
  79. 戻る-1
  80. }
  81. pCodecCtx = pFormatCtx-> streams [videoindex]-> codec
  82. pCodec = avcodec_find_decoder(pCodecCtx-> codec_id)
  83. もし(pCodec == NULL){
  84. printf('Codecnotfound。 n')。
  85. 戻る-1
  86. }
  87. もし(avcodec_open2(pCodecCtx、pCodec、NULL)<0){
  88. printf('コードを開くことができませんでした。 n')。
  89. 戻る-1
  90. }
  91. pFrame = av_frame_alloc()
  92. pFrameYUV = av_frame_alloc()
  93. out_buffer =(unsignedchar*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P、pCodecCtx-> width、pCodecCtx-> height、1))
  94. av_image_fill_arrays(pFrameYUV-> data、pFrameYUV-> linesize、out_buffer、
  95. AV_PIX_FMT_YUV420P、pCodecCtx-> width、pCodecCtx-> height、1)
  96. パケット=(AVPacket *)av_malloc(のサイズ(AVPacket))
  97. // OutputInfo -----------------------------
  98. printf('---------------ファイル情報---------------- n')。
  99. av_dump_format(pFormatCtx、0、ファイルパス、0)
  100. printf('------------------------------------------------- n ')。
  101. img_convert_ctx = sws_getContext(pCodecCtx-> width、pCodecCtx-> height、pCodecCtx-> pix_fmt、
  102. pCodecCtx-> width、pCodecCtx-> height、AV_PIX_FMT_YUV420P、SWS_BICUBIC、NULL、NULL、NULL)
  103. 一方(av_read_frame(pFormatCtx、パケット)> = 0){
  104. もし(パケット-> stream_index == videoindex){
  105. ret = avcodec_decode_video2(pCodecCtx、pFrame、&got_picture、packet)
  106. もし(正しい<0){
  107. printf('DecodeError。 n')。
  108. 戻る-1
  109. }
  110. もし(got_picture){
  111. sws_scale(img_convert_ctx、(const署名なしchar*const*)pFrame-> data、pFrame-> linesize、0、pCodecCtx-> height、
  112. pFrameYUV-> data、pFrameYUV-> linesize)
  113. y_size = pCodecCtx-> width * pCodecCtx-> height
  114. fwrite(pFrameYUV-> data [0]、1、y_size、fp_yuv)//そして
  115. fwrite(pFrameYUV-> data [1]、1、y_size / 4、fp_yuv)// U
  116. fwrite(pFrameYUV-> data [2]、1、y_size / 4、fp_yuv)// V
  117. printf('Succeedtodecode1frame! n')。
  118. }
  119. }
  120. av_free_packet(パケット)
  121. }
  122. // flushdecoder
  123. // FIX:FlushFramesremainedinCodec
  124. 一方(1){
  125. ret = avcodec_decode_video2(pCodecCtx、pFrame、&got_picture、packet)
  126. もし(正しい<0)
  127. ブレーク
  128. もし(!got_picture)
  129. ブレーク
  130. sws_scale(img_convert_ctx、(const署名なしchar*const*)pFrame-> data、pFrame-> linesize、0、pCodecCtx-> height、
  131. pFrameYUV-> data、pFrameYUV-> linesize)
  132. inty_size = pCodecCtx-> width * pCodecCtx-> height
  133. fwrite(pFrameYUV-> data [0]、1、y_size、fp_yuv)//そして
  134. fwrite(pFrameYUV-> data [1]、1、y_size / 4、fp_yuv)// U
  135. fwrite(pFrameYUV-> data [2]、1、y_size / 4、fp_yuv)// V
  136. printf('FlushDecoder:Succeedtodecode1frame! n')。
  137. }
  138. sws_freeContext(img_convert_ctx)
  139. fclose(fp_yuv)
  140. av_frame_free(&pFrameYUV)
  141. av_frame_free(&pFrame)
  142. avcodec_close(pCodecCtx)
  143. avformat_close_input(&pFormatCtx)
  144. 戻る0
  145. }


運転結果

プログラムの実行後、次のビデオファイルがデコードされます。
デコードされたYUV420Pデータはファイルとして保存されます。 YUVプレーヤーを使用して幅と高さを設定した後、YUVコンテンツを表示できます。

SDLピクセルデータプレーヤー

ソースコード

[cpp] プレーンビュー コピー
  1. / **
  2. * SDL2再生ビデオの最も簡単な例(SDL2再生RGB / YUV)
  3. * SimplestVideoPlaySDL2(SDL2playRGB / YUV)
  4. *
  5. *サンダーレイシャオワ
  6. * root @ xxxxx
  7. *中国伝媒大学/デジタルTVテクノロジー
  8. * CommunicationUniversityofChina / DigitalTVTechnology
  9. * http://blog.csdn.net/leixiaohua1020
  10. *
  11. *このプログラムはSDL2を使用してRGB / YUVビデオピクセルデータを再生します。 SDLは実際には基礎となる図面です
  12. * API(Direct3D、OpenGL)カプセル化、基礎となるものを呼び出すために直接使用する方が明らかに簡単です
  13. *火。
  14. *
  15. *関数呼び出しの手順は次のとおりです。
  16. *
  17. * [初期化]
  18. * SDL_Init():SDLを初期化します。
  19. * SDL_CreateWindow():ウィンドウ(Window)を作成します。
  20. * SDL_CreateRenderer():ウィンドウに基づいてレンダラーを作成します。
  21. * SDL_CreateTexture():テクスチャを作成します。
  22. *
  23. * [ループレンダリングデータ]
  24. * SDL_UpdateTexture():テクスチャデータを設定します。
  25. * SDL_RenderCopy():テクスチャがレンダラーにコピーされます。
  26. * SDL_RenderPresent():表示します。
  27. *
  28. *このソフトウェアはSDL2を使用してRGB / YUVrawvideodataを再生します。
  29. * SDLisawrapperoflow-levelAPI(Direct3D、OpenGL)。
  30. *これらの低レベルAPIを直接呼び出すよりもはるかに簡単なSDLismを使用してください。
  31. *
  32. *プロセスは次のとおりです。
  33. *
  34. *[初期化]
  35. * SDL_Init():InitSDL。
  36. * SDL_CreateWindow():CreateaWindow。
  37. * SDL_CreateRenderer():CreateaRender。
  38. * SDL_CreateTexture():CreateaTexture。
  39. *
  40. * [LooptoRenderdata]
  41. * SDL_UpdateTexture():SetTextureのデータ。
  42. * SDL_RenderCopy():CopyTexturetoRender。
  43. * SDL_RenderPresent():表示。
  44. * /
  45. #include
  46. 外部「C」
  47. {{
  48. #include'sdl / SDL.h '
  49. }
  50. constintbpp = 12
  51. intscreen_w = 500、screen_h = 500
  52. constintpixel_w = 320、pixel_h = 180
  53. 署名なしcharbuffer [pixel_w * pixel_h * bpp / 8]
  54. // RefreshEvent
  55. #defineREFRESH_EVENT(SDL_USEREVENT + 1)
  56. #defineBREAK_EVENT(SDL_USEREVENT + 2)
  57. intthread_exit = 0
  58. intrefresh_video(ボイド*不透明){
  59. thread_exit = 0
  60. 一方(!thread_exit){
  61. SDL_Eventevent
  62. event.type = REFRESH_EVENT
  63. SDL_PushEvent(&event)
  64. SDL_Delay(40)
  65. }
  66. thread_exit = 0
  67. //ブレーク
  68. SDL_Eventevent
  69. event.type = BREAK_EVENT
  70. SDL_PushEvent(&event)
  71. 戻る0
  72. }
  73. intメイン(intargc、char* argv [])
  74. {{
  75. もし(SDL_Init(SDL_INIT_VIDEO)){
  76. printf('SDLを初期化できませんでした-%s n'、SDL_GetError())
  77. 戻る-1
  78. }
  79. SDL_Window * screen
  80. //SDL2.0複数のウィンドウのサポート
  81. screen = SDL_CreateWindow(「SimplestVideoPlaySDL2」、SDL_WINDOWPOS_UNDEFINED、SDL_WINDOWPOS_UNDEFINED、
  82. screen_w、screen_h、SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE)
  83. もし(!画面){
  84. printf('SDL:couldnotcreatewindow-exiting:%s n'、SDL_GetError())
  85. 戻る-1
  86. }
  87. SDL_Renderer * sdlRenderer = SDL_CreateRenderer(screen、-1,0)
  88. Uint32pixformat = 0
  89. // IYUV:Y + U + V(3プレーン)
  90. // YV12:Y + V + U(3プレーン)
  91. pixformat = SDL_PIXELFORMAT_IYUV
  92. SDL_Texture * sdlTexture = SDL_CreateTexture(sdlRenderer、pixformat、SDL_TEXTUREACCESS_STREAMING、pixel_w、pixel_h)
  93. ファイル* fp = NULL
  94. fp = fopen('test_yuv420p_320x180.yuv''rb +')。
  95. もし(fp == NULL){
  96. printf('cannotopenthisfile n')。
  97. 戻る-1
  98. }
  99. SDL_RectsdlRect
  100. SDL_Thread * refresh_thread = SDL_CreateThread(refresh_video、NULL、NULL)
  101. SDL_Eventevent
  102. 一方(1){
  103. //待つ
  104. SDL_WaitEvent(&event)
  105. もし(event.type == REFRESH_EVENT){
  106. もし(fread(buffer、1、pixel_w * pixel_h * bpp / 8、fp)!= pixel_w * pixel_h * bpp / 8){
  107. //ループ
  108. fseek(fp、0、SEEK_SET)
  109. fread(buffer、1、pixel_w * pixel_h * bpp / 8、fp)
  110. }
  111. SDL_UpdateTexture(sdlTexture、NULL、buffer、pixel_w)
  112. //修正:Ifwindowisresize
  113. sdlRect.x = 0
  114. sdlRect.y = 0
  115. sdlRect.w = screen_w
  116. sdlRect.h = screen_h
  117. SDL_RenderClear(sdlRenderer)
  118. SDL_RenderCopy(sdlRenderer、sdlTexture、NULL、&sdlRect)
  119. SDL_RenderPresent(sdlRenderer)
  120. }そうしないともし(event.type == SDL_WINDOWEVENT){
  121. // IfResize
  122. SDL_GetWindowSize(screen、&screen_w、&screen_h)
  123. }そうしないともし(event.type == SDL_QUIT){
  124. thread_exit = 1
  125. }そうしないともし(event.type == BREAK_EVENT){
  126. ブレーク
  127. }
  128. }
  129. SDL_Quit()
  130. 戻る0
  131. }

運転結果

プログラムの実行後、以下に示すように、プログラムフォルダの下にあるYUV420Pファイルが読み取られます。
次に、YUVコンテンツがポップアップウィンドウに描画されます。

ダウンロード


最もシンプルなFFmpegプレーヤー


プロジェクトのホームページ

ソースサイト: https://sourceforge.net/projects/simplestffmpegplayer/

Github: https://github.com/leixiaohua1020/simplest_ffmpeg_player

オープンソース中国: http://git.oschina.net/leixiaohua1020/simplest_ffmpeg_player

CSDNダウンロードアドレス: http://download.csdn.net/detail/leixiaohua1020/8924321


このプログラムは、ビデオファイルのデコードと表示を実装します(HEVC、H.264、MPEG2などをサポートします)。
これはFFmpegビデオデコードに関する最も簡単なチュートリアルです。
この例を研究することで、FFmpegのデコードプロセスについて学ぶことができます。
プロジェクトは6つのプロジェクトで構成されています。
simplest_ffmpeg_player:Standard Edition、FFmpeg学習の始まり。
simplest_ffmpeg_player_su:SU(SDL Update)バージョン、単純なSDLイベントが追加されました。
Simplest_ffmpeg_decoder:カプセル化フォーマットの処理を含むデコーダー。 libavcodecとlibavformatが使用されます。
Simplest_ffmpeg_decoder_pure:純粋なデコーダー。 libavcodecのみを使用してください(libavformatは使用しません)。
Simplest_video_play_sdl2:SDL2を使用してYUVを再生する例。
Simplest_ffmpeg_helloworld:FFmpegクラスライブラリに関する情報を出力します。