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