parent
c68887339a
commit
795fe94d56
@ -0,0 +1,12 @@ |
|||||||
|
//
|
||||||
|
// Created by xu fulong on 2022/9/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef FFMPEGANDROID_FFPLAY_DEFINE_H |
||||||
|
#define FFMPEGANDROID_FFPLAY_DEFINE_H |
||||||
|
|
||||||
|
#define PACKET_QUEUE_SIZE 16 |
||||||
|
|
||||||
|
#define FRAME_QUEUE_SIZE 16 |
||||||
|
|
||||||
|
#endif //FFMPEGANDROID_FFPLAY_DEFINE_H
|
@ -0,0 +1,93 @@ |
|||||||
|
|
||||||
|
#include "FrameQueue.h" |
||||||
|
|
||||||
|
FrameQueue::FrameQueue(int max_size, int keep_last):m_size(0), |
||||||
|
m_show_idx(0), |
||||||
|
m_read_idx(0), |
||||||
|
m_write_idx(0), |
||||||
|
m_keep_last(keep_last), |
||||||
|
m_abort_request(0) { |
||||||
|
m_max_size = FFMIN(max_size, FRAME_QUEUE_SIZE); |
||||||
|
memset(m_queue, 0, sizeof(Frame) * FRAME_QUEUE_SIZE); |
||||||
|
|
||||||
|
for (int i = 0; i < this->m_max_size; ++i) { |
||||||
|
m_queue[i].frame = av_frame_alloc(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void FrameQueue::start() { |
||||||
|
std::lock_guard<std::mutex> lock(m_mutex); |
||||||
|
m_abort_request = 0; |
||||||
|
} |
||||||
|
|
||||||
|
void FrameQueue::abort() { |
||||||
|
std::lock_guard<std::mutex> lock(m_mutex); |
||||||
|
m_abort_request = 1; |
||||||
|
} |
||||||
|
|
||||||
|
Frame *FrameQueue::currentFrame() { |
||||||
|
return &m_queue[(m_read_idx + m_show_idx) % m_max_size]; |
||||||
|
} |
||||||
|
|
||||||
|
Frame *FrameQueue::nextFrame() { |
||||||
|
return &m_queue[(m_read_idx + m_show_idx + 1) % m_max_size]; |
||||||
|
} |
||||||
|
|
||||||
|
Frame *FrameQueue::lastFrame() { |
||||||
|
return &m_queue[m_read_idx]; |
||||||
|
} |
||||||
|
|
||||||
|
Frame *FrameQueue::peekWritable() { |
||||||
|
if (m_abort_request) { |
||||||
|
return nullptr; |
||||||
|
} |
||||||
|
|
||||||
|
return &m_queue[m_write_idx]; |
||||||
|
} |
||||||
|
|
||||||
|
void FrameQueue::pushFrame() { |
||||||
|
std::unique_lock<std::mutex> lock(m_mutex); |
||||||
|
if (++m_write_idx == m_max_size) { |
||||||
|
m_write_idx = 0; |
||||||
|
} |
||||||
|
m_size++; |
||||||
|
} |
||||||
|
|
||||||
|
void FrameQueue::popFrame() { |
||||||
|
std::unique_lock<std::mutex> lock(m_mutex); |
||||||
|
if (m_keep_last && !m_show_idx) { |
||||||
|
m_show_idx = 1; |
||||||
|
return; |
||||||
|
} |
||||||
|
unrefFrame(&m_queue[m_read_idx]); |
||||||
|
if (++m_read_idx == m_max_size) { |
||||||
|
m_read_idx = 0; |
||||||
|
} |
||||||
|
m_size--; |
||||||
|
} |
||||||
|
|
||||||
|
void FrameQueue::flush() { |
||||||
|
while (getFrameSize() > 0) { |
||||||
|
popFrame(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
int FrameQueue::getFrameSize() { |
||||||
|
return m_size - m_show_idx; |
||||||
|
} |
||||||
|
|
||||||
|
int FrameQueue::getShowIndex() const { |
||||||
|
return m_show_idx; |
||||||
|
} |
||||||
|
|
||||||
|
void FrameQueue::unrefFrame(Frame *vp) { |
||||||
|
av_frame_unref(vp->frame); |
||||||
|
} |
||||||
|
|
||||||
|
FrameQueue::~FrameQueue() { |
||||||
|
for (int i = 0; i < m_max_size; ++i) { |
||||||
|
Frame *vp = &m_queue[i]; |
||||||
|
unrefFrame(vp); |
||||||
|
av_frame_free(&vp->frame); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,66 @@ |
|||||||
|
|
||||||
|
#ifndef FFMPEGANDROID_FRAMEQUEUE_H |
||||||
|
#define FFMPEGANDROID_FRAMEQUEUE_H |
||||||
|
|
||||||
|
#include <mutex> |
||||||
|
#include "ffplayer/ffplay_define.h" |
||||||
|
|
||||||
|
extern "C" { |
||||||
|
#include "libavcodec/avcodec.h" |
||||||
|
} |
||||||
|
|
||||||
|
typedef struct Frame { |
||||||
|
double pts; |
||||||
|
int width; |
||||||
|
int height; |
||||||
|
int format; |
||||||
|
AVFrame *frame; |
||||||
|
double duration; |
||||||
|
} Frame; |
||||||
|
|
||||||
|
class FrameQueue { |
||||||
|
|
||||||
|
private: |
||||||
|
std::mutex m_mutex; |
||||||
|
int m_abort_request; |
||||||
|
int m_read_idx; |
||||||
|
int m_write_idx; |
||||||
|
int m_size; |
||||||
|
int m_max_size; |
||||||
|
int m_keep_last; |
||||||
|
int m_show_idx; |
||||||
|
Frame m_queue[FRAME_QUEUE_SIZE]; |
||||||
|
|
||||||
|
void unrefFrame(Frame *vp); |
||||||
|
|
||||||
|
public: |
||||||
|
FrameQueue(int max_size, int keep_last); |
||||||
|
|
||||||
|
virtual ~FrameQueue(); |
||||||
|
|
||||||
|
void start(); |
||||||
|
|
||||||
|
void abort(); |
||||||
|
|
||||||
|
Frame *currentFrame(); |
||||||
|
|
||||||
|
Frame *nextFrame(); |
||||||
|
|
||||||
|
Frame *lastFrame(); |
||||||
|
|
||||||
|
Frame *peekWritable(); |
||||||
|
|
||||||
|
void pushFrame(); |
||||||
|
|
||||||
|
void popFrame(); |
||||||
|
|
||||||
|
void flush(); |
||||||
|
|
||||||
|
int getFrameSize(); |
||||||
|
|
||||||
|
int getShowIndex() const; |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
#endif //FFMPEGANDROID_FRAMEQUEUE_H
|
@ -0,0 +1,142 @@ |
|||||||
|
|
||||||
|
#include "PacketQueue.h" |
||||||
|
|
||||||
|
PacketQueue::PacketQueue():m_size(0), |
||||||
|
m_duration(0), |
||||||
|
m_nb_packets(0), |
||||||
|
m_abort_request(0), |
||||||
|
last_pkt_list(nullptr), |
||||||
|
first_pkt_list(nullptr) { |
||||||
|
} |
||||||
|
|
||||||
|
int PacketQueue::put(AVPacket *pkt) { |
||||||
|
PacketList *pkt1; |
||||||
|
|
||||||
|
if (m_abort_request) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
pkt1 = (PacketList *) av_malloc(sizeof(PacketList)); |
||||||
|
if (!pkt1) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
pkt1->pkt = *pkt; |
||||||
|
pkt1->next = nullptr; |
||||||
|
|
||||||
|
if (!last_pkt_list) { |
||||||
|
first_pkt_list = pkt1; |
||||||
|
} else { |
||||||
|
last_pkt_list->next = pkt1; |
||||||
|
} |
||||||
|
|
||||||
|
m_nb_packets++; |
||||||
|
last_pkt_list = pkt1; |
||||||
|
m_size += pkt1->pkt.size + sizeof(*pkt1); |
||||||
|
m_duration += pkt1->pkt.duration; |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
int PacketQueue::pushPacket(AVPacket *pkt) { |
||||||
|
std::unique_lock<std::mutex> lock(m_mutex); |
||||||
|
int ret = put(pkt); |
||||||
|
if (ret < 0) { |
||||||
|
av_packet_unref(pkt); |
||||||
|
} |
||||||
|
m_cond.notify_all(); |
||||||
|
|
||||||
|
return ret; |
||||||
|
} |
||||||
|
|
||||||
|
int PacketQueue::pushEmptyPacket(int stream_idx) { |
||||||
|
AVPacket pkt1; |
||||||
|
AVPacket*pkt = &pkt1; |
||||||
|
av_init_packet(pkt); |
||||||
|
|
||||||
|
pkt->size = 0; |
||||||
|
pkt->data = nullptr; |
||||||
|
pkt->stream_index = stream_idx; |
||||||
|
|
||||||
|
return pushPacket(pkt); |
||||||
|
} |
||||||
|
|
||||||
|
int PacketQueue::popPacket(AVPacket *pkt) { |
||||||
|
std::unique_lock<std::mutex> lock(m_mutex); |
||||||
|
int ret; |
||||||
|
PacketList *pkt1; |
||||||
|
|
||||||
|
for (;;) { |
||||||
|
if (m_abort_request) { |
||||||
|
ret = -1; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
pkt1 = first_pkt_list; |
||||||
|
if (pkt1) { |
||||||
|
first_pkt_list = pkt1->next; |
||||||
|
if (!first_pkt_list) { |
||||||
|
last_pkt_list = nullptr; |
||||||
|
} |
||||||
|
m_nb_packets--; |
||||||
|
m_size -= pkt1->pkt.size + sizeof(*pkt1); |
||||||
|
m_duration -= pkt1->pkt.duration; |
||||||
|
*pkt = pkt1->pkt; |
||||||
|
av_free(pkt1); |
||||||
|
ret = 1; |
||||||
|
break; |
||||||
|
} else { |
||||||
|
m_cond.wait(lock); |
||||||
|
} |
||||||
|
} |
||||||
|
return ret; |
||||||
|
} |
||||||
|
|
||||||
|
void PacketQueue::flush() { |
||||||
|
std::unique_lock<std::mutex> lock(m_mutex); |
||||||
|
PacketList *pkt, *pkt1; |
||||||
|
|
||||||
|
for (pkt = first_pkt_list; pkt; pkt = pkt1) { |
||||||
|
pkt1 = pkt->next; |
||||||
|
av_packet_unref(&pkt->pkt); |
||||||
|
av_freep(&pkt); |
||||||
|
} |
||||||
|
|
||||||
|
m_size = 0; |
||||||
|
m_duration = 0; |
||||||
|
m_nb_packets = 0; |
||||||
|
last_pkt_list = nullptr; |
||||||
|
first_pkt_list = nullptr; |
||||||
|
m_cond.notify_all(); |
||||||
|
} |
||||||
|
|
||||||
|
void PacketQueue::start() { |
||||||
|
std::lock_guard<std::mutex> lock(m_mutex); |
||||||
|
m_abort_request = 0; |
||||||
|
} |
||||||
|
|
||||||
|
void PacketQueue::abort() { |
||||||
|
std::lock_guard<std::mutex> lock(m_mutex); |
||||||
|
m_abort_request = 1; |
||||||
|
} |
||||||
|
|
||||||
|
int PacketQueue::getSize() { |
||||||
|
std::lock_guard<std::mutex> lock(m_mutex); |
||||||
|
return m_size; |
||||||
|
} |
||||||
|
|
||||||
|
int PacketQueue::getPacketSize() { |
||||||
|
std::lock_guard<std::mutex> lock(m_mutex); |
||||||
|
return m_nb_packets; |
||||||
|
} |
||||||
|
|
||||||
|
int64_t PacketQueue::getDuration() { |
||||||
|
return m_duration; |
||||||
|
} |
||||||
|
|
||||||
|
int PacketQueue::isAbortRequest() { |
||||||
|
return m_abort_request; |
||||||
|
} |
||||||
|
|
||||||
|
PacketQueue::~PacketQueue() { |
||||||
|
abort(); |
||||||
|
flush(); |
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
|
||||||
|
#ifndef FFMPEGANDROID_PACKETQUEUE_H |
||||||
|
#define FFMPEGANDROID_PACKETQUEUE_H |
||||||
|
|
||||||
|
|
||||||
|
#include <queue> |
||||||
|
#include <mutex> |
||||||
|
|
||||||
|
extern "C" { |
||||||
|
#include <libavcodec/avcodec.h> |
||||||
|
} |
||||||
|
|
||||||
|
typedef struct PacketList { |
||||||
|
AVPacket pkt; |
||||||
|
struct PacketList *next; |
||||||
|
} PacketList; |
||||||
|
|
||||||
|
class PacketQueue { |
||||||
|
|
||||||
|
private: |
||||||
|
std::mutex m_mutex; |
||||||
|
std::condition_variable m_cond; |
||||||
|
|
||||||
|
int m_size; |
||||||
|
int m_nb_packets; |
||||||
|
int64_t m_duration; |
||||||
|
int m_abort_request; |
||||||
|
PacketList *first_pkt_list; |
||||||
|
PacketList *last_pkt_list; |
||||||
|
|
||||||
|
int put(AVPacket *pkt); |
||||||
|
|
||||||
|
public: |
||||||
|
|
||||||
|
PacketQueue(); |
||||||
|
|
||||||
|
int pushPacket(AVPacket *pkt); |
||||||
|
|
||||||
|
int pushEmptyPacket(int stream_idx); |
||||||
|
|
||||||
|
int popPacket(AVPacket *pkt); |
||||||
|
|
||||||
|
void flush(); |
||||||
|
|
||||||
|
void start(); |
||||||
|
|
||||||
|
void abort(); |
||||||
|
|
||||||
|
int getSize(); |
||||||
|
|
||||||
|
int getPacketSize(); |
||||||
|
|
||||||
|
int64_t getDuration(); |
||||||
|
|
||||||
|
int isAbortRequest(); |
||||||
|
|
||||||
|
virtual ~PacketQueue(); |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
#endif //FFMPEGANDROID_PACKETQUEUE_H
|
Loading…
Reference in new issue