Feature: add PacketQueue and FrameQueue

pull/221/head
xufuji456 2 years ago
parent c68887339a
commit 795fe94d56
  1. 5
      app/src/main/cpp/CMakeLists.txt
  2. 12
      app/src/main/cpp/ffplayer/ffplay_define.h
  3. 93
      app/src/main/cpp/ffplayer/queue/FrameQueue.cpp
  4. 66
      app/src/main/cpp/ffplayer/queue/FrameQueue.h
  5. 142
      app/src/main/cpp/ffplayer/queue/PacketQueue.cpp
  6. 62
      app/src/main/cpp/ffplayer/queue/PacketQueue.h

@ -32,6 +32,10 @@ set(SRC_METADATA
metadata/metadata_util.c
metadata/ffmpeg_media_retriever.c)
set(SRC_FFPLAYER
ffplayer/queue/FrameQueue.cpp
ffplayer/queue/PacketQueue.cpp)
add_library( # Sets the name of the library.
media-handle
@ -42,6 +46,7 @@ add_library( # Sets the name of the library.
${SRC_FFMPEG}
${SRC_VISUALIZER}
${SRC_METADATA}
${SRC_FFPLAYER}
video_player.cpp
video_filter.c
ffprobe_cmd.cpp

@ -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…
Cancel
Save