mirror of
https://github.com/Almamu/linux-wallpaperengine.git
synced 2025-09-14 13:56:48 +08:00
Moves code related to rendering from Core::CVideo to Render::CVideo
This commit is contained in:
parent
3079b42cc4
commit
067aea6543
@ -4,114 +4,14 @@ using namespace WallpaperEngine::Core;
|
||||
|
||||
CVideo::CVideo (
|
||||
const irr::io::path& filename) :
|
||||
CWallpaper (Type)
|
||||
CWallpaper (Type),
|
||||
m_filename (filename)
|
||||
{
|
||||
if (avformat_open_input (&m_formatCtx, filename.c_str(), NULL, NULL) < 0)
|
||||
throw std::runtime_error ("Failed to open file");
|
||||
|
||||
if (avformat_find_stream_info (m_formatCtx, NULL) < 0)
|
||||
throw std::runtime_error ("Failed to get stream info");
|
||||
|
||||
// Find first video stream
|
||||
for (int i = 0; i < m_formatCtx->nb_streams; i++)
|
||||
{
|
||||
if (m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||
{
|
||||
m_videoStream = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find first audio stream
|
||||
for (int i = 0; i < m_formatCtx->nb_streams; i++)
|
||||
const irr::io::path CVideo::getFilename ()
|
||||
{
|
||||
if (m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
|
||||
{
|
||||
m_audioStream = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Only video stream is required
|
||||
if (m_videoStream == -1)
|
||||
throw std::runtime_error ("Failed to find video stream");
|
||||
|
||||
AVCodec* codec = avcodec_find_decoder (m_formatCtx->streams[m_videoStream]->codecpar->codec_id);
|
||||
if (codec == nullptr)
|
||||
throw std::runtime_error ("Failed to find codec");
|
||||
|
||||
m_codecCtx = avcodec_alloc_context3 (codec);
|
||||
if (avcodec_parameters_to_context (m_codecCtx, m_formatCtx->streams[m_videoStream]->codecpar))
|
||||
throw std::runtime_error ("Failed to copy codec parameters");
|
||||
|
||||
if (avcodec_open2 (m_codecCtx, codec, NULL) < 0)
|
||||
throw std::runtime_error ("Failed to open codec");
|
||||
|
||||
m_videoFrame = av_frame_alloc ();
|
||||
m_videoFrameRGB = av_frame_alloc ();
|
||||
if (m_videoFrameRGB == nullptr)
|
||||
throw std::runtime_error ("Failed to allocate video frame");
|
||||
}
|
||||
|
||||
void CVideo::setSize (int width, int height)
|
||||
{
|
||||
if (buffer != nullptr)
|
||||
av_free (buffer);
|
||||
|
||||
if (m_swsCtx != nullptr)
|
||||
sws_freeContext (m_swsCtx);
|
||||
|
||||
int numBytes = av_image_get_buffer_size (AV_PIX_FMT_RGB24, width, height, 1);
|
||||
buffer = (uint8_t*)av_malloc (numBytes * sizeof (uint8_t));
|
||||
|
||||
av_image_fill_arrays (m_videoFrameRGB->data, m_videoFrameRGB->linesize, buffer, AV_PIX_FMT_RGB24, width, height, 1);
|
||||
|
||||
m_swsCtx = sws_getContext (m_codecCtx->width, m_codecCtx->height,
|
||||
m_codecCtx->pix_fmt,
|
||||
width, height,
|
||||
AV_PIX_FMT_RGB24,
|
||||
SWS_BILINEAR, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void CVideo::restartStream ()
|
||||
{
|
||||
av_seek_frame (m_formatCtx, m_videoStream, 0, AVSEEK_FLAG_FRAME);
|
||||
avcodec_flush_buffers (m_codecCtx);
|
||||
}
|
||||
|
||||
AVFormatContext* CVideo::getFormatContext ()
|
||||
{
|
||||
return this->m_formatCtx;
|
||||
}
|
||||
|
||||
AVCodecContext* CVideo::getCodecContext ()
|
||||
{
|
||||
return this->m_codecCtx;
|
||||
}
|
||||
|
||||
AVFrame* CVideo::getVideoFrame ()
|
||||
{
|
||||
return this->m_videoFrame;
|
||||
}
|
||||
|
||||
AVFrame* CVideo::getVideoFrameRGB ()
|
||||
{
|
||||
return this->m_videoFrameRGB;
|
||||
}
|
||||
|
||||
SwsContext* CVideo::getSwsContext ()
|
||||
{
|
||||
return this->m_swsCtx;
|
||||
}
|
||||
|
||||
int CVideo::getVideoStreamIndex ()
|
||||
{
|
||||
return this->m_videoStream;
|
||||
}
|
||||
|
||||
int CVideo::getAudioStreamIndex ()
|
||||
{
|
||||
return this->m_audioStream;
|
||||
return this->m_filename;
|
||||
}
|
||||
|
||||
const std::string CVideo::Type = "video";
|
||||
|
@ -22,30 +22,15 @@ namespace WallpaperEngine::Core
|
||||
const irr::io::path& filename
|
||||
);
|
||||
|
||||
void setSize (int width, int height);
|
||||
void restartStream ();
|
||||
|
||||
AVFormatContext* getFormatContext ();
|
||||
AVCodecContext* getCodecContext ();
|
||||
AVFrame* getVideoFrame ();
|
||||
AVFrame* getVideoFrameRGB ();
|
||||
SwsContext* getSwsContext ();
|
||||
int getVideoStreamIndex ();
|
||||
int getAudioStreamIndex ();
|
||||
const irr::io::path getFilename ();
|
||||
|
||||
protected:
|
||||
friend class CWallpaper;
|
||||
|
||||
const irr::io::path m_filename;
|
||||
|
||||
static const std::string Type;
|
||||
|
||||
private:
|
||||
AVFormatContext* m_formatCtx = nullptr;
|
||||
AVCodecContext* m_codecCtx = nullptr;
|
||||
AVFrame* m_videoFrame = nullptr;
|
||||
AVFrame* m_videoFrameRGB = nullptr;
|
||||
SwsContext* m_swsCtx = nullptr;
|
||||
uint8_t* buffer = nullptr;
|
||||
|
||||
int m_videoStream = -1, m_audioStream = -1;
|
||||
};
|
||||
};
|
||||
|
@ -7,6 +7,71 @@ using namespace WallpaperEngine::Render;
|
||||
CVideo::CVideo (Core::CVideo* video, WallpaperEngine::Irrlicht::CContext* context) :
|
||||
CWallpaper (video, Type, context)
|
||||
{
|
||||
if (avformat_open_input (&m_formatCtx, video->getFilename ().c_str (), NULL, NULL) < 0)
|
||||
throw std::runtime_error ("Failed to open video file");
|
||||
|
||||
if (avformat_find_stream_info (m_formatCtx, NULL) < 0)
|
||||
throw std::runtime_error ("Failed to get stream info");
|
||||
|
||||
// Find first video stream
|
||||
for (int i = 0; i < m_formatCtx->nb_streams; i++)
|
||||
{
|
||||
if (m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||
{
|
||||
m_videoStream = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find first audio stream
|
||||
for (int i = 0; i < m_formatCtx->nb_streams; i++)
|
||||
{
|
||||
if (m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
|
||||
{
|
||||
m_audioStream = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Only video stream is required
|
||||
if (m_videoStream == -1)
|
||||
throw std::runtime_error ("Failed to find video stream");
|
||||
|
||||
AVCodec* codec = avcodec_find_decoder (m_formatCtx->streams[m_videoStream]->codecpar->codec_id);
|
||||
if (codec == nullptr)
|
||||
throw std::runtime_error ("Failed to find codec");
|
||||
|
||||
m_codecCtx = avcodec_alloc_context3 (codec);
|
||||
if (avcodec_parameters_to_context (m_codecCtx, m_formatCtx->streams[m_videoStream]->codecpar))
|
||||
throw std::runtime_error ("Failed to copy codec parameters");
|
||||
|
||||
if (avcodec_open2 (m_codecCtx, codec, NULL) < 0)
|
||||
throw std::runtime_error ("Failed to open codec");
|
||||
|
||||
m_videoFrame = av_frame_alloc ();
|
||||
m_videoFrameRGB = av_frame_alloc ();
|
||||
if (m_videoFrameRGB == nullptr)
|
||||
throw std::runtime_error ("Failed to allocate video frame");
|
||||
}
|
||||
|
||||
void CVideo::setSize (int width, int height)
|
||||
{
|
||||
if (m_buffer != nullptr)
|
||||
av_free (m_buffer);
|
||||
|
||||
if (m_swsCtx != nullptr)
|
||||
sws_freeContext (m_swsCtx);
|
||||
|
||||
int numBytes = av_image_get_buffer_size (AV_PIX_FMT_RGB24, width, height, 1);
|
||||
m_buffer = (uint8_t*)av_malloc (numBytes * sizeof (uint8_t));
|
||||
|
||||
av_image_fill_arrays (m_videoFrameRGB->data, m_videoFrameRGB->linesize, m_buffer, AV_PIX_FMT_RGB24, width, height, 1);
|
||||
|
||||
m_swsCtx = sws_getContext (m_codecCtx->width, m_codecCtx->height,
|
||||
m_codecCtx->pix_fmt,
|
||||
width, height,
|
||||
AV_PIX_FMT_RGB24,
|
||||
SWS_BILINEAR, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void CVideo::render ()
|
||||
@ -18,7 +83,7 @@ void CVideo::render ()
|
||||
m_frameImage = m_context->getDevice ()->getVideoDriver ()->createImage (irr::video::ECOLOR_FORMAT::ECF_R8G8B8,
|
||||
irr::core::dimension2du(width, height));
|
||||
|
||||
getVideo ()->setSize (width, height);
|
||||
setSize (width, height);
|
||||
getNextFrame ();
|
||||
writeFrameToImage ();
|
||||
|
||||
@ -31,7 +96,6 @@ void CVideo::render ()
|
||||
|
||||
void CVideo::getNextFrame ()
|
||||
{
|
||||
Core::CVideo* videoData = getVideo ();
|
||||
bool eof = false;
|
||||
AVPacket packet;
|
||||
packet.data = nullptr;
|
||||
@ -42,7 +106,7 @@ void CVideo::getNextFrame ()
|
||||
if (packet.data != nullptr)
|
||||
av_packet_unref (&packet);
|
||||
|
||||
int readError = av_read_frame (videoData->getFormatContext (), &packet);
|
||||
int readError = av_read_frame (m_formatCtx, &packet);
|
||||
if (readError == AVERROR_EOF)
|
||||
{
|
||||
eof = true;
|
||||
@ -54,28 +118,28 @@ void CVideo::getNextFrame ()
|
||||
throw std::runtime_error (av_make_error_string (err, AV_ERROR_MAX_STRING_SIZE, readError));
|
||||
}
|
||||
|
||||
} while (packet.stream_index != videoData->getVideoStreamIndex ());
|
||||
} while (packet.stream_index != m_videoStream);
|
||||
|
||||
// Send video stream packet to codec
|
||||
if (avcodec_send_packet (videoData->getCodecContext (), &packet) < 0)
|
||||
if (avcodec_send_packet (m_codecCtx, &packet) < 0)
|
||||
return;
|
||||
|
||||
// Receive frame from codec
|
||||
if (avcodec_receive_frame (videoData->getCodecContext (), videoData->getVideoFrame ()) < 0)
|
||||
if (avcodec_receive_frame (m_codecCtx, m_videoFrame) < 0)
|
||||
return;
|
||||
|
||||
sws_scale (videoData->getSwsContext (), (uint8_t const* const*)videoData->getVideoFrame ()->data, videoData->getVideoFrame ()->linesize,
|
||||
0, videoData->getCodecContext ()->height, videoData->getVideoFrameRGB ()->data, videoData->getVideoFrameRGB ()->linesize);
|
||||
sws_scale (m_swsCtx, (uint8_t const* const*)m_videoFrame->data, m_videoFrame->linesize,
|
||||
0, m_codecCtx->height, m_videoFrameRGB->data, m_videoFrameRGB->linesize);
|
||||
|
||||
av_packet_unref (&packet);
|
||||
|
||||
if (eof)
|
||||
videoData->restartStream ();
|
||||
restartStream ();
|
||||
}
|
||||
|
||||
void CVideo::writeFrameToImage ()
|
||||
{
|
||||
uint8_t* frameData = getVideo ()->getVideoFrameRGB ()->data[0];
|
||||
uint8_t* frameData = m_videoFrameRGB->data[0];
|
||||
if (frameData == nullptr)
|
||||
return;
|
||||
|
||||
@ -87,6 +151,12 @@ void CVideo::writeFrameToImage ()
|
||||
m_frameImage->unlock ();
|
||||
}
|
||||
|
||||
void CVideo::restartStream ()
|
||||
{
|
||||
av_seek_frame (m_formatCtx, m_videoStream, 0, AVSEEK_FLAG_FRAME);
|
||||
avcodec_flush_buffers (m_codecCtx);
|
||||
}
|
||||
|
||||
Core::CVideo* CVideo::getVideo ()
|
||||
{
|
||||
return this->getWallpaperData ()->as<Core::CVideo> ();
|
||||
|
@ -33,9 +33,19 @@ namespace WallpaperEngine::Render
|
||||
static const std::string Type;
|
||||
|
||||
private:
|
||||
void setSize (int width, int height);
|
||||
void restartStream ();
|
||||
void getNextFrame ();
|
||||
void writeFrameToImage ();
|
||||
|
||||
AVFormatContext* m_formatCtx = nullptr;
|
||||
AVCodecContext* m_codecCtx = nullptr;
|
||||
AVFrame* m_videoFrame = nullptr;
|
||||
AVFrame* m_videoFrameRGB = nullptr;
|
||||
SwsContext* m_swsCtx = nullptr;
|
||||
uint8_t* m_buffer = nullptr;
|
||||
int m_videoStream = -1, m_audioStream = -1;
|
||||
|
||||
irr::video::IImage* m_frameImage;
|
||||
irr::video::ITexture* m_frameTexture;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user