1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

CVideoHandler: use new ffmpeg

This commit is contained in:
Konstantin 2022-05-10 19:25:48 +03:00 committed by Andrii Danylchenko
parent 1e97859fbf
commit e7b753c222
2 changed files with 36 additions and 25 deletions

View File

@ -72,11 +72,6 @@ CVideoPlayer::CVideoPlayer()
refreshWait = 0;
refreshCount = 0;
doLoop = false;
// Register codecs. TODO: May be overkill. Should call a
// combination of av_register_input_format() /
// av_register_output_format() / av_register_protocol() instead.
av_register_all();
}
bool CVideoPlayer::open(std::string fname, bool scale)
@ -127,7 +122,7 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal
stream = -1;
for(ui32 i=0; i<format->nb_streams; i++)
{
if (format->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
if (format->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
stream = i;
break;
@ -138,11 +133,8 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal
// No video stream in that file
return false;
// Get a pointer to the codec context for the video stream
codecContext = format->streams[stream]->codec;
// Find the decoder for the video stream
codec = avcodec_find_decoder(codecContext->codec_id);
codec = avcodec_find_decoder(format->streams[stream]->codecpar->codec_id);
if (codec == nullptr)
{
@ -150,6 +142,15 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay, bool scal
return false;
}
codecContext = avcodec_alloc_context3(codec);
// Get a pointer to the codec context for the video stream
int ret = avcodec_parameters_to_context(codecContext, format->streams[stream]->codecpar);
if (ret < 0)
{
//We cannot get codec from parameters
return false;
}
// Open codec
if ( avcodec_open2(codecContext, codec, nullptr) < 0 )
{
@ -266,24 +267,28 @@ bool CVideoPlayer::nextFrame()
if (packet.stream_index == stream)
{
// Decode video frame
avcodec_decode_video2(codecContext, frame, &frameFinished, &packet);
int rc = avcodec_send_packet(codecContext, &packet);
if (rc >=0)
packet.size = 0;
rc = avcodec_receive_frame(codecContext, frame);
if (rc >= 0)
frameFinished = 1;
// Did we get a video frame?
if (frameFinished)
{
AVPicture pict;
uint8_t *data[4];
int linesize[4];
if (texture) {
avpicture_alloc(&pict, AV_PIX_FMT_YUV420P, pos.w, pos.h);
av_image_alloc(data, linesize, pos.w, pos.h, AV_PIX_FMT_YUV420P, 1);
sws_scale(sws, frame->data, frame->linesize,
0, codecContext->height, pict.data, pict.linesize);
0, codecContext->height, data, linesize);
SDL_UpdateYUVTexture(texture, NULL, pict.data[0], pict.linesize[0],
pict.data[1], pict.linesize[1],
pict.data[2], pict.linesize[2]);
avpicture_free(&pict);
SDL_UpdateYUVTexture(texture, NULL, data[0], linesize[0],
data[1], linesize[1],
data[2], linesize[2]);
av_freep(&data[0]);
}
else
{
@ -306,18 +311,18 @@ bool CVideoPlayer::nextFrame()
size_t pic_bytes = dest->pitch * dest->h;
size_t ffmped_pad = 1024; /* a few bytes of overflow will go here */
void * for_sws = av_malloc (pic_bytes + ffmped_pad);
pict.data[0] = (ui8 *)for_sws;
pict.linesize[0] = dest->pitch;
data[0] = (ui8 *)for_sws;
linesize[0] = dest->pitch;
sws_scale(sws, frame->data, frame->linesize,
0, codecContext->height, pict.data, pict.linesize);
0, codecContext->height, data, linesize);
memcpy(dest->pixels, for_sws, pic_bytes);
av_free(for_sws);
}
}
}
av_free_packet(&packet);
av_packet_unref(&packet);
}
}
@ -401,6 +406,10 @@ void CVideoPlayer::close()
{
avcodec_close(codecContext);
codec = nullptr;
}
if (codecContext)
{
avcodec_free_context(&codecContext);
codecContext = nullptr;
}

View File

@ -59,6 +59,8 @@ public:
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
}
@ -94,7 +96,7 @@ class CVideoPlayer : public IMainVideoPlayer
int stream; // stream index in video
AVFormatContext *format;
AVCodecContext *codecContext; // codec context for stream
AVCodec *codec;
const AVCodec *codec;
AVFrame *frame;
struct SwsContext *sws;