Resolves #6088 by rolling our own PacketList that replaces the deprecated AVPacketList; initial work done by akortunov in 60aec04606; adapted and cleaned up some old cruft along the way.

librecast_all_the_things
Bret Curtis 3 years ago committed by Bret Curtis
parent c3d3535ffd
commit 4eea734551

@ -4,10 +4,12 @@
#include <cassert> #include <cassert>
#include <cstddef> #include <cstddef>
#include <iostream> #include <iostream>
#include <memory>
#include <thread> #include <thread>
#include <chrono> #include <chrono>
#include <osg/Texture2D> #include <osg/Texture2D>
#include <utility>
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma warning (push) #pragma warning (push)
@ -62,20 +64,20 @@ namespace
av_frame_free(&frame); av_frame_free(&frame);
} }
}; };
template<class T>
struct AVFree
{
void operator()(T* frame) const
{
av_free(&frame);
}
};
} }
namespace Video namespace Video
{ {
struct PacketListFree
{
void operator()(Video::PacketList* list) const
{
av_packet_free(&list->pkt);
av_free(&list);
}
};
VideoState::VideoState() VideoState::VideoState()
: mAudioFactory(nullptr) : mAudioFactory(nullptr)
, format_ctx(nullptr) , format_ctx(nullptr)
@ -114,25 +116,29 @@ void VideoState::setAudioFactory(MovieAudioFactory *factory)
void PacketQueue::put(AVPacket *pkt) void PacketQueue::put(AVPacket *pkt)
{ {
std::unique_ptr<AVPacketList, AVFree<AVPacketList>> pkt1(static_cast<AVPacketList*>(av_malloc(sizeof(AVPacketList)))); std::unique_ptr<PacketList, PacketListFree> pkt1(static_cast<PacketList*>(av_malloc(sizeof(PacketList))));
if(!pkt1) throw std::bad_alloc(); if(!pkt1) throw std::bad_alloc();
if(pkt == &flush_pkt) if(pkt == &flush_pkt)
pkt1->pkt = *pkt; pkt1->pkt = pkt;
else else
av_packet_move_ref(&pkt1->pkt, pkt); {
pkt1->pkt = av_packet_alloc();
av_packet_move_ref(pkt1->pkt, pkt);
}
pkt1->next = nullptr; pkt1->next = nullptr;
std::lock_guard<std::mutex> lock(this->mutex); std::lock_guard<std::mutex> lock(this->mutex);
AVPacketList* ptr = pkt1.release(); PacketList* ptr = pkt1.release();
if(!last_pkt) if(!last_pkt)
this->first_pkt = ptr; this->first_pkt = ptr;
else else
this->last_pkt->next = ptr; this->last_pkt->next = ptr;
this->last_pkt = ptr; this->last_pkt = ptr;
this->nb_packets++; this->nb_packets++;
this->size += ptr->pkt.size; this->size += ptr->pkt->size;
this->cond.notify_one(); this->cond.notify_one();
} }
@ -141,17 +147,17 @@ int PacketQueue::get(AVPacket *pkt, VideoState *is)
std::unique_lock<std::mutex> lock(this->mutex); std::unique_lock<std::mutex> lock(this->mutex);
while(!is->mQuit) while(!is->mQuit)
{ {
AVPacketList *pkt1 = this->first_pkt; PacketList *pkt1 = this->first_pkt;
if(pkt1) if(pkt1)
{ {
this->first_pkt = pkt1->next; this->first_pkt = pkt1->next;
if(!this->first_pkt) if(!this->first_pkt)
this->last_pkt = nullptr; this->last_pkt = nullptr;
this->nb_packets--; this->nb_packets--;
this->size -= pkt1->pkt.size; this->size -= pkt1->pkt->size;
av_packet_unref(pkt); av_packet_unref(pkt);
av_packet_move_ref(pkt, &pkt1->pkt); av_packet_move_ref(pkt, pkt1->pkt);
av_free(pkt1); av_free(pkt1);
return 1; return 1;
@ -173,14 +179,14 @@ void PacketQueue::flush()
void PacketQueue::clear() void PacketQueue::clear()
{ {
AVPacketList *pkt, *pkt1; PacketList *pkt, *pkt1;
std::lock_guard<std::mutex> lock(this->mutex); std::lock_guard<std::mutex> lock(this->mutex);
for(pkt = this->first_pkt; pkt != nullptr; pkt = pkt1) for(pkt = this->first_pkt; pkt != nullptr; pkt = pkt1)
{ {
pkt1 = pkt->next; pkt1 = pkt->next;
if (pkt->pkt.data != flush_pkt.data) if (pkt->pkt->data != flush_pkt.data)
av_packet_unref(&pkt->pkt); av_packet_unref(pkt->pkt);
av_freep(&pkt); av_freep(&pkt);
} }
this->last_pkt = nullptr; this->last_pkt = nullptr;
@ -415,7 +421,7 @@ double VideoState::synchronize_video(const AVFrame &src_frame, double pts)
class VideoThread class VideoThread
{ {
public: public:
VideoThread(VideoState* self) explicit VideoThread(VideoState* self)
: mVideoState(self) : mVideoState(self)
, mThread([this] , mThread([this]
{ {
@ -439,9 +445,8 @@ public:
void run() void run()
{ {
VideoState* self = mVideoState; VideoState* self = mVideoState;
AVPacket packetData; AVPacket* packetData = av_packet_alloc();
av_init_packet(&packetData); std::unique_ptr<AVPacket, AVPacketUnref> packet(packetData);
std::unique_ptr<AVPacket, AVPacketUnref> packet(&packetData);
std::unique_ptr<AVFrame, AVFrameFree> pFrame{av_frame_alloc()}; std::unique_ptr<AVFrame, AVFrameFree> pFrame{av_frame_alloc()};
while(self->videoq.get(packet.get(), self) >= 0) while(self->videoq.get(packet.get(), self) >= 0)
@ -491,7 +496,7 @@ private:
class ParseThread class ParseThread
{ {
public: public:
ParseThread(VideoState* self) explicit ParseThread(VideoState* self)
: mVideoState(self) : mVideoState(self)
, mThread([this] { run(); }) , mThread([this] { run(); })
{ {
@ -507,9 +512,8 @@ public:
VideoState* self = mVideoState; VideoState* self = mVideoState;
AVFormatContext *pFormatCtx = self->format_ctx; AVFormatContext *pFormatCtx = self->format_ctx;
AVPacket packetData; AVPacket* packetData = av_packet_alloc();
av_init_packet(&packetData); std::unique_ptr<AVPacket, AVPacketUnref> packet(packetData);
std::unique_ptr<AVPacket, AVPacketUnref> packet(&packetData);
try try
{ {
@ -632,13 +636,11 @@ bool VideoState::update()
int VideoState::stream_open(int stream_index, AVFormatContext *pFormatCtx) int VideoState::stream_open(int stream_index, AVFormatContext *pFormatCtx)
{ {
const AVCodec *codec;
if(stream_index < 0 || stream_index >= static_cast<int>(pFormatCtx->nb_streams)) if(stream_index < 0 || stream_index >= static_cast<int>(pFormatCtx->nb_streams))
return -1; return -1;
// Get a pointer to the codec context for the video stream // Get a pointer to the codec context for the video stream
codec = avcodec_find_decoder(pFormatCtx->streams[stream_index]->codecpar->codec_id); const AVCodec *codec = avcodec_find_decoder(pFormatCtx->streams[stream_index]->codecpar->codec_id);
if(!codec) if(!codec)
{ {
fprintf(stderr, "Unsupported codec!\n"); fprintf(stderr, "Unsupported codec!\n");
@ -702,7 +704,7 @@ int VideoState::stream_open(int stream_index, AVFormatContext *pFormatCtx)
return -1; return -1;
} }
this->video_thread.reset(new VideoThread(this)); this->video_thread = std::make_unique<VideoThread>(this);
break; break;
default: default:
@ -721,7 +723,7 @@ void VideoState::init(std::shared_ptr<std::istream> inputstream, const std::stri
this->av_sync_type = AV_SYNC_DEFAULT; this->av_sync_type = AV_SYNC_DEFAULT;
this->mQuit = false; this->mQuit = false;
this->stream = inputstream; this->stream = std::move(inputstream);
if(!this->stream.get()) if(!this->stream.get())
throw std::runtime_error("Failed to open video resource"); throw std::runtime_error("Failed to open video resource");
@ -789,7 +791,7 @@ void VideoState::init(std::shared_ptr<std::istream> inputstream, const std::stri
} }
this->parse_thread.reset(new ParseThread(this)); this->parse_thread = std::make_unique<ParseThread>(this);
} }
void VideoState::deinit() void VideoState::deinit()
@ -801,11 +803,11 @@ void VideoState::deinit()
mAudioDecoder.reset(); mAudioDecoder.reset();
if (this->parse_thread.get()) if (this->parse_thread)
{ {
this->parse_thread.reset(); this->parse_thread.reset();
} }
if (this->video_thread.get()) if (this->video_thread)
{ {
this->video_thread.reset(); this->video_thread.reset();
} }
@ -851,8 +853,8 @@ void VideoState::deinit()
} }
// Dellocate RGBA frame queue. // Dellocate RGBA frame queue.
for (std::size_t i = 0; i < VIDEO_PICTURE_ARRAY_SIZE; ++i) for (auto & i : this->pictq)
this->pictq[i].rgbaFrame = nullptr; i.rgbaFrame = nullptr;
} }
@ -870,7 +872,7 @@ double VideoState::get_master_clock()
return this->get_external_clock(); return this->get_external_clock();
} }
double VideoState::get_video_clock() double VideoState::get_video_clock() const
{ {
return this->frame_last_pts; return this->frame_last_pts;
} }
@ -896,7 +898,7 @@ void VideoState::seekTo(double time)
mSeekRequested = true; mSeekRequested = true;
} }
double VideoState::getDuration() double VideoState::getDuration() const
{ {
return this->format_ctx->duration / 1000000.0; return this->format_ctx->duration / 1000000.0;
} }

@ -46,7 +46,6 @@ extern "C"
extern "C" extern "C"
{ {
struct SwsContext; struct SwsContext;
struct AVPacketList;
struct AVPacket; struct AVPacket;
struct AVFormatContext; struct AVFormatContext;
struct AVStream; struct AVStream;
@ -78,6 +77,13 @@ struct ExternalClock
void set(uint64_t time); void set(uint64_t time);
}; };
class PacketList
{
public:
AVPacket* pkt = nullptr;
PacketList *next = nullptr;
};
struct PacketQueue { struct PacketQueue {
PacketQueue() PacketQueue()
: first_pkt(nullptr), last_pkt(nullptr), flushing(false), nb_packets(0), size(0) : first_pkt(nullptr), last_pkt(nullptr), flushing(false), nb_packets(0), size(0)
@ -85,7 +91,7 @@ struct PacketQueue {
~PacketQueue() ~PacketQueue()
{ clear(); } { clear(); }
AVPacketList *first_pkt, *last_pkt; PacketList *first_pkt, *last_pkt;
std::atomic<bool> flushing; std::atomic<bool> flushing;
std::atomic<int> nb_packets; std::atomic<int> nb_packets;
std::atomic<int> size; std::atomic<int> size;
@ -129,7 +135,7 @@ struct VideoState {
void setPaused(bool isPaused); void setPaused(bool isPaused);
void seekTo(double time); void seekTo(double time);
double getDuration(); double getDuration() const;
int stream_open(int stream_index, AVFormatContext *pFormatCtx); int stream_open(int stream_index, AVFormatContext *pFormatCtx);
@ -145,7 +151,7 @@ struct VideoState {
double synchronize_video(const AVFrame &src_frame, double pts); double synchronize_video(const AVFrame &src_frame, double pts);
double get_audio_clock(); double get_audio_clock();
double get_video_clock(); double get_video_clock() const;
double get_external_clock(); double get_external_clock();
double get_master_clock(); double get_master_clock();

Loading…
Cancel
Save