mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-29 16:06:44 +00:00
add PacketGuard and move try/catch up
This commit is contained in:
parent
1b61ec979d
commit
3b7cef9e88
1 changed files with 80 additions and 54 deletions
134
extern/osg-ffmpeg-videoplayer/videostate.cpp
vendored
134
extern/osg-ffmpeg-videoplayer/videostate.cpp
vendored
|
@ -37,6 +37,39 @@ namespace
|
||||||
{
|
{
|
||||||
const int MAX_AUDIOQ_SIZE = (5 * 16 * 1024);
|
const int MAX_AUDIOQ_SIZE = (5 * 16 * 1024);
|
||||||
const int MAX_VIDEOQ_SIZE = (5 * 256 * 1024);
|
const int MAX_VIDEOQ_SIZE = (5 * 256 * 1024);
|
||||||
|
|
||||||
|
class PacketGuard
|
||||||
|
{
|
||||||
|
AVPacket mPacket;
|
||||||
|
bool mReleased;
|
||||||
|
public:
|
||||||
|
PacketGuard() : mReleased(false)
|
||||||
|
{
|
||||||
|
av_init_packet(&mPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
AVPacket* operator->()
|
||||||
|
{
|
||||||
|
return &mPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
AVPacket* operator*()
|
||||||
|
{
|
||||||
|
return &mPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
AVPacket* release()
|
||||||
|
{
|
||||||
|
mReleased = true;
|
||||||
|
return &mPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
~PacketGuard()
|
||||||
|
{
|
||||||
|
if(!mReleased)
|
||||||
|
av_packet_unref(&mPacket);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Video
|
namespace Video
|
||||||
|
@ -98,7 +131,7 @@ void PacketQueue::put(AVPacket *pkt)
|
||||||
this->last_pkt->next = pkt1.get();
|
this->last_pkt->next = pkt1.get();
|
||||||
this->last_pkt = pkt1.release();
|
this->last_pkt = pkt1.release();
|
||||||
this->nb_packets++;
|
this->nb_packets++;
|
||||||
this->size += pkt1->pkt.size;
|
this->size += this->last_pkt->pkt.size;
|
||||||
this->cond.notify_one();
|
this->cond.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,7 +416,17 @@ class VideoThread
|
||||||
public:
|
public:
|
||||||
VideoThread(VideoState* self)
|
VideoThread(VideoState* self)
|
||||||
: mVideoState(self)
|
: mVideoState(self)
|
||||||
, mThread([this] { run(); })
|
, mThread([this]
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
run();
|
||||||
|
}
|
||||||
|
catch(std::exception& e)
|
||||||
|
{
|
||||||
|
std::cerr << "An error occurred playing the video: " << e.what () << std::endl;
|
||||||
|
}
|
||||||
|
})
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,60 +438,46 @@ public:
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
VideoState* self = mVideoState;
|
VideoState* self = mVideoState;
|
||||||
AVPacket pkt1, *packet = &pkt1;
|
PacketGuard packet;
|
||||||
av_init_packet(packet);
|
std::unique_ptr<AVFrame, VideoPicture::AVFrameDeleter> pFrame{av_frame_alloc()};
|
||||||
AVFrame *pFrame;
|
|
||||||
|
|
||||||
pFrame = av_frame_alloc();
|
while(self->videoq.get(*packet, self) >= 0)
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
while(self->videoq.get(packet, self) >= 0)
|
if(packet->data == flush_pkt.data)
|
||||||
{
|
{
|
||||||
if(packet->data == flush_pkt.data)
|
avcodec_flush_buffers(self->video_ctx);
|
||||||
|
|
||||||
|
self->pictq_mutex.lock();
|
||||||
|
self->pictq_size = 0;
|
||||||
|
self->pictq_rindex = 0;
|
||||||
|
self->pictq_windex = 0;
|
||||||
|
self->pictq_mutex.unlock();
|
||||||
|
|
||||||
|
self->frame_last_pts = packet->pts * av_q2d((*self->video_st)->time_base);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode video frame
|
||||||
|
int ret = avcodec_send_packet(self->video_ctx, *packet);
|
||||||
|
// EAGAIN is not expected
|
||||||
|
if (ret < 0)
|
||||||
|
throw std::runtime_error("Error decoding video frame");
|
||||||
|
|
||||||
|
while (!ret)
|
||||||
|
{
|
||||||
|
ret = avcodec_receive_frame(self->video_ctx, pFrame.get());
|
||||||
|
if (!ret)
|
||||||
{
|
{
|
||||||
avcodec_flush_buffers(self->video_ctx);
|
double pts = pFrame->best_effort_timestamp;
|
||||||
|
pts *= av_q2d((*self->video_st)->time_base);
|
||||||
|
|
||||||
self->pictq_mutex.lock();
|
pts = self->synchronize_video(pFrame.get(), pts);
|
||||||
self->pictq_size = 0;
|
|
||||||
self->pictq_rindex = 0;
|
|
||||||
self->pictq_windex = 0;
|
|
||||||
self->pictq_mutex.unlock();
|
|
||||||
|
|
||||||
self->frame_last_pts = packet->pts * av_q2d((*self->video_st)->time_base);
|
if(self->queue_picture(pFrame.get(), pts) < 0)
|
||||||
continue;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
// Decode video frame
|
|
||||||
int ret = avcodec_send_packet(self->video_ctx, packet);
|
|
||||||
// EAGAIN is not expected
|
|
||||||
if (ret < 0)
|
|
||||||
throw std::runtime_error("Error decoding video frame");
|
|
||||||
|
|
||||||
while (!ret)
|
|
||||||
{
|
|
||||||
ret = avcodec_receive_frame(self->video_ctx, pFrame);
|
|
||||||
if (!ret)
|
|
||||||
{
|
|
||||||
double pts = pFrame->best_effort_timestamp;
|
|
||||||
pts *= av_q2d((*self->video_st)->time_base);
|
|
||||||
|
|
||||||
pts = self->synchronize_video(pFrame, pts);
|
|
||||||
|
|
||||||
if(self->queue_picture(pFrame, pts) < 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << "An error occurred playing the video: " << e.what () << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
av_packet_unref(packet);
|
|
||||||
|
|
||||||
av_frame_free(&pFrame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -475,8 +504,7 @@ public:
|
||||||
VideoState* self = mVideoState;
|
VideoState* self = mVideoState;
|
||||||
|
|
||||||
AVFormatContext *pFormatCtx = self->format_ctx;
|
AVFormatContext *pFormatCtx = self->format_ctx;
|
||||||
AVPacket pkt1, *packet = &pkt1;
|
PacketGuard packet;
|
||||||
av_init_packet(packet);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -559,7 +587,7 @@ public:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(av_read_frame(pFormatCtx, packet) < 0)
|
if(av_read_frame(pFormatCtx, *packet) < 0)
|
||||||
{
|
{
|
||||||
if (self->audioq.nb_packets == 0 && self->videoq.nb_packets == 0 && self->pictq_size == 0)
|
if (self->audioq.nb_packets == 0 && self->videoq.nb_packets == 0 && self->pictq_size == 0)
|
||||||
self->mVideoEnded = true;
|
self->mVideoEnded = true;
|
||||||
|
@ -570,11 +598,9 @@ public:
|
||||||
|
|
||||||
// Is this a packet from the video stream?
|
// Is this a packet from the video stream?
|
||||||
if(self->video_st && packet->stream_index == self->video_st-pFormatCtx->streams)
|
if(self->video_st && packet->stream_index == self->video_st-pFormatCtx->streams)
|
||||||
self->videoq.put(packet);
|
self->videoq.put(packet.release());
|
||||||
else if(self->audio_st && packet->stream_index == self->audio_st-pFormatCtx->streams)
|
else if(self->audio_st && packet->stream_index == self->audio_st-pFormatCtx->streams)
|
||||||
self->audioq.put(packet);
|
self->audioq.put(packet.release());
|
||||||
else
|
|
||||||
av_packet_unref(packet);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(std::exception& e) {
|
catch(std::exception& e) {
|
||||||
|
|
Loading…
Reference in a new issue