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