FFMPEG 无法显示YUV图像

红色代码 红色代码 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
不好意思,直接上代码了.问题是用avcodec_decode_video2解码出一帧原始数据可以绘出图像,但是用sws_scale转换YUV数据后就是绿油油一片,哪里出问题了?

#include "StdAfx.h"
#include "MediaPlayer.h"
#include <atlconv.h>


Uint8* CMediaPlayer::m_pAudioPos = nullptr;
Uint32 CMediaPlayer::m_nAudioLen = 0;

CMediaPlayer::CMediaPlayer(void): m_pFrameContext(nullptr),
m_hReadFrameThread(nullptr),
m_bReadFrameThreadExit(false),
m_pSdlWindow(nullptr),
m_pSdlRenderer(nullptr),
m_pSdlTexture(nullptr),
m_pSwsContext(nullptr)
{
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
}

CMediaPlayer::~CMediaPlayer(void)
{
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER);
}

//---------------------------------------------------------------------------------
void CMediaPlayer::Release()
{
}

//---------------------------------------------------------------------------------
bool CMediaPlayer::Open(const TCHAR* sUrl)
{
if (nullptr == sUrl)
return false;

av_register_all();
USES_CONVERSION;
const char* sAnsiUrl = W2A(sUrl);
if (nullptr == m_pFrameContext)
m_pFrameContext = avformat_alloc_context();

if (avformat_open_input(&m_pFrameContext, sAnsiUrl, nullptr, nullptr) < 0)
return false;

if (avformat_find_stream_info(m_pFrameContext, nullptr) < 0)
return false;

int nBestStreamIndex = -1;
int nStream = m_pFrameContext->nb_streams;
for (int i = 0; i < nStream; i++)
{
AVStream* pStream = m_pFrameContext->streams[i];
if (nullptr == pStream) continue;

AVCodecContext* pCodecContext = pStream->codec;
if (nullptr == pCodecContext) continue;

AVCodec* pCodec = avcodec_find_decoder(pCodecContext->codec_id);
if (nullptr == pCodec) continue;

nBestStreamIndex = av_find_best_stream(m_pFrameContext, pCodec->type, -1, -1, nullptr, 0);
if (i != nBestStreamIndex)
continue;

if (avcodec_open2(pCodecContext, pCodec, nullptr) < 0)
continue;

m_codecContexts.push_back(pStream);
}

// 初始化视频设备
AVCodecContext* pVideoCodecContext = FindCodecContext(AVMEDIA_TYPE_VIDEO);
int nScreenWidth = pVideoCodecContext->width;
int nScreenHeight = pVideoCodecContext->height;

m_pSwsContext = sws_getContext(nScreenWidth, nScreenHeight, pVideoCodecContext->pix_fmt,
nScreenWidth, nScreenHeight, AV_PIX_FMT_YUV420P,
SWS_BICUBIC, nullptr, nullptr, nullptr);

if (nullptr == m_pSdlWindow)
m_pSdlWindow = SDL_CreateWindow("My VPlayer",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, nScreenWidth, nScreenHeight, SDL_WINDOW_OPENGL);
if (nullptr == m_pSdlWindow) return false;

if (nullptr == m_pSdlRenderer)
m_pSdlRenderer = SDL_CreateRenderer(m_pSdlWindow, -1, 0);
if (nullptr == m_pSdlRenderer) return false;

if (nullptr == m_pSdlTexture)
m_pSdlTexture = SDL_CreateTexture(m_pSdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, nScreenWidth, nScreenHeight);
if (nullptr == m_pSdlTexture) return false;

int nLayoutNbChannels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO);
// 打开声音设备
AVCodecContext* pAudioCodecContext = FindCodecContext(AVMEDIA_TYPE_AUDIO);
if (nullptr != pAudioCodecContext)
{
SDL_AudioSpec sdlAudioSpec = {0};
sdlAudioSpec.freq = 44100;
sdlAudioSpec.samples = pAudioCodecContext->frame_size;
sdlAudioSpec.channels = nLayoutNbChannels;;
sdlAudioSpec.format = AUDIO_S16SYS ;
sdlAudioSpec.silence = 0;
sdlAudioSpec.callback = SDL_AudioCallback;
sdlAudioSpec.userdata = nullptr;

if (-1 == SDL_OpenAudio(&sdlAudioSpec, nullptr))
return false;

m_nAudioLen = av_samples_get_buffer_size(nullptr, nLayoutNbChannels, pAudioCodecContext->frame_size, AV_SAMPLE_FMT_S16, 1);
}

if (nullptr == m_hReadFrameThread)
m_hReadFrameThread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)_ReadFrameThread, this, 0, nullptr);
if (nullptr == m_hReadFrameThread)
return false;

return true;
}

//---------------------------------------------------------------------------------
void CMediaPlayer::Close()
{
if (nullptr != m_hReadFrameThread)
{
m_bReadFrameThreadExit = true;
WaitForSingleObject(m_hReadFrameThread,INFINITE);
CloseHandle(m_hReadFrameThread);
m_hReadFrameThread = nullptr;
}

SDL_CloseAudio();

if (nullptr != m_pSwsContext)
{
sws_freeContext(m_pSwsContext);
m_pSwsContext = nullptr;
}

if (nullptr != m_pSdlTexture)
{
SDL_DestroyTexture(m_pSdlTexture);
m_pSdlTexture = nullptr;
}

if (nullptr != m_pSdlRenderer)
{
SDL_DestroyRenderer(m_pSdlRenderer);
m_pSdlRenderer = nullptr;
}

if (nullptr != m_pSdlWindow)
{
SDL_DestroyWindow(m_pSdlWindow);
m_pSdlWindow = nullptr;
}

CODEC_CONTEXTS::const_iterator cit = m_codecContexts.begin();
for (cit; cit != m_codecContexts.end(); ++cit)
{
AVStream* pStream = *cit;
if (nullptr == pStream) continue;
AVCodecContext* pCodecContext = pStream->codec;
if (nullptr == pCodecContext) continue;
avcodec_close(pCodecContext);
pCodecContext = nullptr;
}

m_codecContexts.clear();

if (nullptr != m_pFrameContext)
{
avformat_close_input(&m_pFrameContext);
avformat_free_context(m_pFrameContext);
m_pFrameContext = nullptr;
}
}

//---------------------------------------------------------------------------------
void CMediaPlayer::Pause()
{
}

//---------------------------------------------------------------------------------
void CMediaPlayer::Resume()
{
}

//---------------------------------------------------------------------------------
void CMediaPlayer::Seek(long nTime)
{
}

//---------------------------------------------------------------------------------
unsigned long __stdcall CMediaPlayer::_ReadFrameThread(CMediaPlayer* pThis)
{
if (nullptr == pThis)
return -1;

return pThis->ReadFrameLoop();
}

//---------------------------------------------------------------------------------
unsigned long CMediaPlayer::ReadFrameLoop()
{
AVCodecContext* pVideoCodecContext = FindCodecContext(AVMEDIA_TYPE_VIDEO);
AVCodecContext* pAudioCodecContext = FindCodecContext(AVMEDIA_TYPE_AUDIO);
AVCodecContext* pSubTitleCodecContext = FindCodecContext(AVMEDIA_TYPE_SUBTITLE);

int nVideoStreamIndex = FindCodecStreamIndex(AVMEDIA_TYPE_VIDEO);
int nAudioStreamIndex = FindCodecStreamIndex(AVMEDIA_TYPE_AUDIO);
int nSubTitleStreamIndex = FindCodecStreamIndex(AVMEDIA_TYPE_SUBTITLE);
int got_picture = 0;
AVPacket pkt = {nullptr};
av_init_packet(&pkt);

AVFrame* frame = av_frame_alloc();
AVFrame* pFrameYUV = av_frame_alloc();
av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, nullptr,
AV_PIX_FMT_YUV420P, pVideoCodecContext->width, pVideoCodecContext->height, 1);

while (!m_bReadFrameThreadExit)
{
while (av_read_frame(m_pFrameContext, &pkt) >= 0 && (!m_bReadFrameThreadExit))
{
if (pkt.stream_index == nVideoStreamIndex)
{
if (avcodec_decode_video2(pVideoCodecContext, frame, &got_picture, &pkt) < 0)
{
_tprintf(_T("Decode Video Failed\r\n"));
return -1;
}

if (got_picture <= 0) continue;

// 显示图像
sws_scale(m_pSwsContext, (const unsigned char* const*)frame->data,
frame->linesize, 0, pVideoCodecContext->height,
pFrameYUV->data, pFrameYUV->linesize);

SDL_UpdateTexture(m_pSdlTexture, nullptr, pFrameYUV->data[0], pFrameYUV->linesize[0]);
SDL_RenderClear(m_pSdlRenderer);
SDL_RenderCopy(m_pSdlRenderer, m_pSdlTexture, nullptr, nullptr);
SDL_RenderPresent(m_pSdlRenderer);
}
else if (pkt.stream_index == nAudioStreamIndex)
{
if (avcodec_decode_audio4(pAudioCodecContext, frame, &got_picture, &pkt) < 0)
{
_tprintf(_T("Decode Audio Failed\r\n"));
return -2;
}

if (0 == got_picture) continue;

m_pAudioPos = (Uint8*)frame->data;
}
}
}

if (nullptr != pFrameYUV)
{
av_frame_free(&pFrameYUV);
pFrameYUV = nullptr;
}

if (nullptr != frame)
{
av_frame_free(&frame);
frame = nullptr;
}

av_free_packet(&pkt);

return 0;
}

//---------------------------------------------------------------------------------
AVCodecContext* CMediaPlayer::FindCodecContext(AVMediaType mediaType)
{
AVCodecContext* pContext = nullptr;
CODEC_CONTEXTS::const_iterator cit = m_codecContexts.begin();
for (cit; cit != m_codecContexts.end(); ++cit)
{
AVStream* pStream = *cit;
if (nullptr == pStream) continue;

AVCodecContext* pCodecContext = pStream->codec;
if (nullptr == pCodecContext) continue;
if (pCodecContext->codec->type == mediaType)
{
pContext = pCodecContext;
break;
}
}

return pContext;
}

//---------------------------------------------------------------------------------
int CMediaPlayer::FindCodecStreamIndex(AVMediaType mediaType)
{
int nStreamIndex = -1;
CODEC_CONTEXTS::const_iterator cit = m_codecContexts.begin();
for (cit; cit != m_codecContexts.end(); ++cit)
{
AVStream* pStream = *cit;
if (nullptr == pStream) continue;

AVCodecContext* pCodecContext = pStream->codec;
if (nullptr == pCodecContext) continue;
if (pCodecContext->codec->type == mediaType)
{
nStreamIndex = pStream->index;
break;
}
}

return nStreamIndex;
}

//---------------------------------------------------------------------------------
void CMediaPlayer::SDL_AudioCallback(void* userdata, Uint8* stream, int len)
{
if (m_nAudioLen <= 0) return;

SDL_MixAudio(stream, m_pAudioPos, len,SDL_MIX_MAXVOLUME);
m_pAudioPos += len;
m_nAudioLen -= len;
}

...全文

相关推荐

ffmpeg视频解码成YUV,JPG

**注意事项** - 在处理YUV文件时,需要确保输出文件的大小与视频原始分辨率匹配,否则可能会出现图像错位或无法正确显示的情况。

月棠

【FFMPEG】YUV420P格式图像叠加,拼接

YUV420P格式图像叠加,拼接 网上的很多代码都有问题!!! 话不多说上代码: 需要用到库: ffmpeg,用于解码h264,也可以直接用yuv图像进行拼接,只要记住yuv420p的数据存放格式和采样格式就不会出错。 sdl2,用于实时显示 #include &lt;stdio.h&gt; #include &lt;sstream&gt; #include &lt;string&gt; #i...

LaoLi0519

【FFmpeg命令】jpg与yuv(批量)互转

目录1. 单图像jpg转yuv2. 单图像yuv转jpg3. 批量jpg转yuv3.1 bat文件3.2 python的PIL模块3.3 实现思路3.4 参考代码3.5 小问题4. 批量yuv转jpg FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序,其命令行十分丰富。 关于FFmpeg的安装与配置,上一篇博文已经做过介绍了,此文不再赘述。本文重点讲解如何使用 FFmpeg 命令行实现 jpg 与 yuv 图像格式的相互转换,并支持批量化。 1. 单图像jpg转yuv 倘

《哈哈论》

bgr24转yuv420提取自ffmpeg代码,不依赖ffmpeg

然而,提取出的代码不依赖于ffmpeg,这意味着我们可以独立实现这个转换过程,这对于那些无法或不想引入整个ffmpeg库的项目来说是有益的。

ce6581281

软件实现一张YUV数据某个区域马赛克算法(mosaic)完整源码

由于没有具体的源码内容,我们无法详细讨论代码实现细节,但可以推测其可能使用C++、C#、Python或其他支持图像处理的编程语言编写,并可能依赖于OpenCV、FFmpeg等图像处理库。

「已注销」
评论 1
收藏 已收藏
分享
返回顶部
红色代码
图象工具使用 1,451 成员 24,331 内容