parent
							
								
									e661b3211a
								
							
						
					
					
						commit
						1a9f81ec2f
					
				| @ -1,192 +0,0 @@ | ||||
| 
 | ||||
| #include "FFMessageQueue.h" | ||||
| 
 | ||||
| inline static void msg_free(AVMessage *msg) { | ||||
|     if (!msg || !msg->obj) | ||||
|         return; | ||||
|     assert(msg->free_l); | ||||
|     msg->free_l(msg->obj); | ||||
|     msg->obj = nullptr; | ||||
| } | ||||
| 
 | ||||
| inline static int msg_queue_put_private(MessageQueue *q, AVMessage *msg) { | ||||
|     AVMessage *msg1; | ||||
| 
 | ||||
|     if (q->abort_request) | ||||
|         return -1; | ||||
| 
 | ||||
|     msg1 = q->recycle_msg; | ||||
|     if (msg1) { | ||||
|         q->recycle_msg = msg1->next; | ||||
|         q->recycle_count++; | ||||
|     } else { | ||||
|         q->alloc_count++; | ||||
|         msg1 = static_cast<AVMessage *>(av_malloc(sizeof(AVMessage))); | ||||
|     } | ||||
| 
 | ||||
|     if (!msg1) | ||||
|         return -1; | ||||
| 
 | ||||
|     *msg1 = *msg; | ||||
|     msg1->next = nullptr; | ||||
| 
 | ||||
|     if (!q->last_msg) | ||||
|         q->first_msg = msg1; | ||||
|     else | ||||
|         q->last_msg->next = msg1; | ||||
|     q->last_msg = msg1; | ||||
|     q->nb_messages++; | ||||
|     q->cond.notify_all(); | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| inline static int msg_queue_put(MessageQueue *q, AVMessage *msg) { | ||||
|     int ret; | ||||
| 
 | ||||
|     std::lock_guard<std::mutex> lock(q->mutex); | ||||
|     ret = msg_queue_put_private(q, msg); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| inline static void msg_init_msg(AVMessage *msg) { | ||||
|     memset(msg, 0, sizeof(AVMessage)); | ||||
| } | ||||
| 
 | ||||
| void FFMessageQueue::init() { | ||||
|     memset(q, 0, sizeof(MessageQueue)); | ||||
|     q->abort_request = 1; | ||||
| } | ||||
| 
 | ||||
| void FFMessageQueue::start() { | ||||
|     std::lock_guard<std::mutex> lock(q->mutex); | ||||
|     q->abort_request = 0; | ||||
| 
 | ||||
|     AVMessage msg; | ||||
|     msg_init_msg(&msg); | ||||
|     msg.what = FFP_MSG_FLUSH; | ||||
|     msg_queue_put_private(q, &msg); | ||||
| } | ||||
| 
 | ||||
| void FFMessageQueue::flush() { | ||||
|     AVMessage *msg, *msg1; | ||||
|     std::lock_guard<std::mutex> lock(q->mutex); | ||||
| 
 | ||||
|     for (msg = q->first_msg; msg != NULL; msg = msg1) { | ||||
|         msg1 = msg->next; | ||||
|         msg->next = q->recycle_msg; | ||||
|         q->recycle_msg = msg; | ||||
|     } | ||||
|     q->last_msg = nullptr; | ||||
|     q->first_msg = nullptr; | ||||
|     q->nb_messages = 0; | ||||
| } | ||||
| 
 | ||||
| void FFMessageQueue::sendMessage1(int what) { | ||||
|     AVMessage msg; | ||||
|     msg_init_msg(&msg); | ||||
|     msg.what = what; | ||||
|     msg_queue_put(q, &msg); | ||||
| } | ||||
| 
 | ||||
| void FFMessageQueue::sendMessage2(int what, int arg1) { | ||||
|     AVMessage msg; | ||||
|     msg_init_msg(&msg); | ||||
|     msg.what = what; | ||||
|     msg.arg1 = arg1; | ||||
|     msg_queue_put(q, &msg); | ||||
| } | ||||
| 
 | ||||
| void FFMessageQueue::sendMessage3(int what, int arg1, int arg2) { | ||||
|     AVMessage msg; | ||||
|     msg_init_msg(&msg); | ||||
|     msg.what = what; | ||||
|     msg.arg1 = arg1; | ||||
|     msg.arg2 = arg2; | ||||
|     msg_queue_put(q, &msg); | ||||
| } | ||||
| 
 | ||||
| int FFMessageQueue::get(AVMessage *msg, int block) { | ||||
|     AVMessage *msg1; | ||||
|     int ret; | ||||
| 
 | ||||
|     std::unique_lock<std::mutex> lock(q->mutex); | ||||
| 
 | ||||
|     for (;;) { | ||||
|         if (q->abort_request) { | ||||
|             ret = -1; | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         msg1 = q->first_msg; | ||||
|         if (msg1) { | ||||
|             q->first_msg = msg1->next; | ||||
|             if (!q->first_msg) | ||||
|                 q->last_msg = nullptr; | ||||
|             q->nb_messages--; | ||||
|             *msg = *msg1; | ||||
|             msg1->obj = nullptr; | ||||
|             msg1->next = q->recycle_msg; | ||||
|             q->recycle_msg = msg1; | ||||
|             ret = 1; | ||||
|             break; | ||||
|         } else if (!block) { | ||||
|             ret = 0; | ||||
|             break; | ||||
|         } else { | ||||
|             q->cond.wait(lock); | ||||
|         } | ||||
|     } | ||||
|     lock.unlock(); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| void FFMessageQueue::remove(int what) { | ||||
|     AVMessage **p_msg, *msg, *last_msg; | ||||
|     std::lock_guard<std::mutex> lock(q->mutex); | ||||
| 
 | ||||
|     last_msg = q->first_msg; | ||||
| 
 | ||||
|     if (!q->abort_request && q->first_msg) { | ||||
|         p_msg = &q->first_msg; | ||||
|         while (*p_msg) { | ||||
|             msg = *p_msg; | ||||
| 
 | ||||
|             if (msg->what == what) { | ||||
|                 *p_msg = msg->next; | ||||
|                 msg_free(msg); | ||||
|                 msg->next = q->recycle_msg; | ||||
|                 q->recycle_msg = msg; | ||||
|                 q->nb_messages--; | ||||
|             } else { | ||||
|                 last_msg = msg; | ||||
|                 p_msg = &msg->next; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (q->first_msg) { | ||||
|             q->last_msg = last_msg; | ||||
|         } else { | ||||
|             q->last_msg = nullptr; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void FFMessageQueue::abort() { | ||||
|     std::unique_lock<std::mutex> lock(q->mutex); | ||||
|     q->abort_request = 1; | ||||
|     q->cond.notify_all(); | ||||
| } | ||||
| 
 | ||||
| void FFMessageQueue::destroy() { | ||||
|     flush(); | ||||
|     std::lock_guard<std::mutex> lock(q->mutex); | ||||
| 
 | ||||
|     while(q->recycle_msg) { | ||||
|         AVMessage *msg = q->recycle_msg; | ||||
|         if (msg) | ||||
|             q->recycle_msg = msg->next; | ||||
|         msg_free(msg); | ||||
|         av_freep(&msg); | ||||
|     } | ||||
| } | ||||
| @ -1,96 +0,0 @@ | ||||
| 
 | ||||
| #ifndef FFMPEGANDROID_FFMESSAGEQUEUE_H | ||||
| #define FFMPEGANDROID_FFMESSAGEQUEUE_H | ||||
| 
 | ||||
| #include <mutex> | ||||
| #include <libavutil/mem.h> | ||||
| 
 | ||||
| /**************** msg  define begin ***************/ | ||||
| 
 | ||||
| #define FFP_MSG_FLUSH                       0 | ||||
| #define FFP_MSG_ERROR                       100 | ||||
| #define FFP_MSG_PREPARED                    200 | ||||
| #define FFP_MSG_COMPLETED                   300 | ||||
| #define FFP_MSG_VIDEO_SIZE_CHANGED          400 | ||||
| #define FFP_MSG_SAR_CHANGED                 401 | ||||
| #define FFP_MSG_VIDEO_RENDERING_START       402 | ||||
| #define FFP_MSG_AUDIO_RENDERING_START       403 | ||||
| #define FFP_MSG_VIDEO_ROTATION_CHANGED      404 | ||||
| #define FFP_MSG_AUDIO_DECODED_START         405 | ||||
| #define FFP_MSG_VIDEO_DECODED_START         406 | ||||
| #define FFP_MSG_OPEN_INPUT                  407 | ||||
| #define FFP_MSG_FIND_STREAM_INFO            408 | ||||
| #define FFP_MSG_COMPONENT_OPEN              409 | ||||
| #define FFP_MSG_VIDEO_SEEK_RENDERING_START  410 | ||||
| #define FFP_MSG_AUDIO_SEEK_RENDERING_START  411 | ||||
| #define FFP_MSG_DECODER_OPEN_ERROR          412 | ||||
| #define FFP_MSG_DEMUX_ERROR                 413 | ||||
| 
 | ||||
| #define FFP_MSG_BUFFERING_START             500 | ||||
| #define FFP_MSG_BUFFERING_END               501 | ||||
| #define FFP_MSG_BUFFERING_UPDATE            502 | ||||
| #define FFP_MSG_BUFFERING_BYTES_UPDATE      503 | ||||
| #define FFP_MSG_BUFFERING_TIME_UPDATE       504 | ||||
| #define FFP_MSG_SEEK_COMPLETE               600 | ||||
| #define FFP_MSG_PLAYBACK_STATE_CHANGED      700 | ||||
| #define FFP_MSG_TIMED_TEXT                  800 | ||||
| #define FFP_MSG_VIDEO_DECODER_OPEN          900 | ||||
| #define FFP_MSG_OPEN_ERROR                  901 | ||||
| 
 | ||||
| #define FFP_REQ_START                       1001 | ||||
| #define FFP_REQ_PAUSE                       1002 | ||||
| #define FFP_REQ_SEEK                        1003 | ||||
| 
 | ||||
| /**************** msg  define end *****************/ | ||||
| 
 | ||||
| typedef struct AVMessage { | ||||
|     int what; | ||||
|     int arg1; | ||||
|     int arg2; | ||||
|     void *obj; | ||||
|     void (*free_l)(void *obj); | ||||
|     struct AVMessage *next; | ||||
| } AVMessage; | ||||
| 
 | ||||
| typedef struct MessageQueue { | ||||
|     AVMessage *first_msg, *last_msg; | ||||
|     int nb_messages; | ||||
|     int abort_request; | ||||
|     std::mutex mutex; | ||||
|     std::condition_variable cond; | ||||
| 
 | ||||
|     AVMessage *recycle_msg; | ||||
|     int recycle_count; | ||||
|     int alloc_count; | ||||
| } MessageQueue; | ||||
| 
 | ||||
| class FFMessageQueue { | ||||
| 
 | ||||
| private: | ||||
|     MessageQueue *q; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     void init(); | ||||
| 
 | ||||
|     void start(); | ||||
| 
 | ||||
|     void flush(); | ||||
| 
 | ||||
|     void sendMessage1(int what); | ||||
| 
 | ||||
|     void sendMessage2(int what, int arg1); | ||||
| 
 | ||||
|     void sendMessage3(int what, int arg1, int arg2); | ||||
| 
 | ||||
|     int get(AVMessage *msg, int block); | ||||
| 
 | ||||
|     void remove(int what); | ||||
| 
 | ||||
|     void abort(); | ||||
| 
 | ||||
|     void destroy(); | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #endif //FFMPEGANDROID_FFMESSAGEQUEUE_H
 | ||||
| @ -1,50 +0,0 @@ | ||||
| 
 | ||||
| #include <ffplay_define.h> | ||||
| #include "MediaClock.h" | ||||
| 
 | ||||
| MediaClock::MediaClock() { | ||||
|     m_speed = 1.0; | ||||
|     m_pause = false; | ||||
|     setClock(NAN); | ||||
| } | ||||
| 
 | ||||
| void MediaClock::setClock(double pts) { | ||||
|     double time = (double) av_gettime_relative() / 1000000.0; | ||||
|     setClock(pts, time); | ||||
| } | ||||
| 
 | ||||
| void MediaClock::setClock(double pts, double time) { | ||||
|     m_pts         = pts; | ||||
|     m_last_update = time; | ||||
|     m_pts_drift   = m_pts - time; | ||||
| } | ||||
| 
 | ||||
| double MediaClock::getClock() const { | ||||
|     if (m_pause) { | ||||
|         return m_pts; | ||||
|     } else { | ||||
|         double time = (double) av_gettime_relative() / 1000000.0; | ||||
|         return m_pts_drift + time - (time - m_last_update) * (1.0 - m_speed); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void MediaClock::setSpeed(double speed) { | ||||
|     setClock(getClock()); | ||||
|     m_speed = speed; | ||||
| } | ||||
| 
 | ||||
| double MediaClock::getSpeed() const { | ||||
|     return m_speed; | ||||
| } | ||||
| 
 | ||||
| void MediaClock::syncToSlave(MediaClock *slave) { | ||||
|     double clock = getClock(); | ||||
|     double slave_clock = slave->getClock(); | ||||
|     if (!isnan(slave_clock) && (isnan(clock) || fabs(clock - slave_clock) > AV_NOSYNC_THRESHOLD)) { | ||||
|         setClock(slave_clock); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| MediaClock::~MediaClock() { | ||||
| 
 | ||||
| } | ||||
| @ -1,45 +0,0 @@ | ||||
| 
 | ||||
| #ifndef FFMPEGANDROID_MEDIACLOCK_H | ||||
| #define FFMPEGANDROID_MEDIACLOCK_H | ||||
| 
 | ||||
| #include <math.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| #include <libavutil/time.h> | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| class MediaClock { | ||||
| 
 | ||||
| private: | ||||
|     bool m_pause; | ||||
|     double m_pts; | ||||
|     double m_speed; | ||||
|     double m_pts_drift; | ||||
|     double m_last_update; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     MediaClock(); | ||||
| 
 | ||||
|     void setClock(double pts); | ||||
| 
 | ||||
|     void setClock(double pts, double time); | ||||
| 
 | ||||
|     double getClock() const; | ||||
| 
 | ||||
|     void setSpeed(double speed); | ||||
| 
 | ||||
|     double getSpeed() const; | ||||
| 
 | ||||
|     void syncToSlave(MediaClock *slave); | ||||
| 
 | ||||
|     virtual ~MediaClock(); | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #endif //FFMPEGANDROID_MEDIACLOCK_H
 | ||||
| @ -1,98 +0,0 @@ | ||||
| 
 | ||||
| #ifndef FFMPEGANDROID_FFPLAY_DEFINE_H | ||||
| #define FFMPEGANDROID_FFPLAY_DEFINE_H | ||||
| 
 | ||||
| #include <mutex> | ||||
| #include "FFMessageQueue.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| #include <libavformat/avformat.h> | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #define PACKET_QUEUE_SIZE 16 | ||||
| #define FRAME_QUEUE_SIZE 16 | ||||
| 
 | ||||
| #define VIDEO_QUEUE_SIZE 5 | ||||
| #define SAMPLE_QUEUE_SIZE 9 | ||||
| 
 | ||||
| #define MAX_QUEUE_SIZE (15 * 1024 * 1024) | ||||
| #define MIN_FRAMES 25 | ||||
| 
 | ||||
| #define AUDIO_MIN_BUFFER_SIZE 512 | ||||
| #define AUDIO_MAX_CALLBACKS_PER_SEC 30 | ||||
| 
 | ||||
| #define REFRESH_RATE 0.01 | ||||
| 
 | ||||
| #define AV_SYNC_THRESHOLD_MIN 0.04 | ||||
| #define AV_SYNC_THRESHOLD_MAX 0.1 | ||||
| #define AV_SYNC_FRAMEDUP_THRESHOLD 0.1 | ||||
| #define AV_NOSYNC_THRESHOLD 10.0 | ||||
| 
 | ||||
| #define EXTERNAL_CLOCK_MIN_FRAMES 2 | ||||
| #define EXTERNAL_CLOCK_MAX_FRAMES 10 | ||||
| #define EXTERNAL_CLOCK_SPEED_MIN  0.900 | ||||
| #define EXTERNAL_CLOCK_SPEED_MAX  1.010 | ||||
| #define EXTERNAL_CLOCK_SPEED_STEP 0.001 | ||||
| 
 | ||||
| struct AVDictionary { | ||||
|     int count; | ||||
|     AVDictionaryEntry *elements; | ||||
| }; | ||||
| 
 | ||||
| typedef enum { | ||||
|     AV_SYNC_AUDIO,      // 同步到音频时钟
 | ||||
|     AV_SYNC_VIDEO,      // 同步到视频时钟
 | ||||
|     AV_SYNC_EXTERNAL,   // 同步到外部时钟
 | ||||
| } SyncType; | ||||
| 
 | ||||
| class PlayerParams { | ||||
| 
 | ||||
| public: | ||||
|     std::mutex mutex; | ||||
| 
 | ||||
|     FFMessageQueue *messageQueue; | ||||
|     int64_t videoDuration; | ||||
| 
 | ||||
|     AVInputFormat *iformat; | ||||
|     const char *url; | ||||
|     int64_t offset; | ||||
|     const char *headers; | ||||
| 
 | ||||
|     const char *audioCodecName; | ||||
|     const char *videoCodecName; | ||||
| 
 | ||||
|     int abortRequest; | ||||
|     int pauseRequest; | ||||
|     SyncType syncType; | ||||
|     int64_t startTime; | ||||
|     int64_t duration; | ||||
|     int realTime; | ||||
|     int infiniteBuffer; | ||||
|     int audioDisable; | ||||
|     int videoDisable; | ||||
|     int displayDisable; | ||||
| 
 | ||||
|     int fast; | ||||
|     int genpts; | ||||
|     int lowres; | ||||
| 
 | ||||
|     float playbackRate; | ||||
|     float playbackPitch; | ||||
| 
 | ||||
|     int seekByBytes; | ||||
|     int seekRequest; | ||||
|     int seekFlags; | ||||
|     int64_t seekPos; | ||||
|     int64_t seekRel; | ||||
| 
 | ||||
|     int autoExit; | ||||
|     int loop; | ||||
|     int mute; | ||||
|     int reorderVideoPts; | ||||
| }; | ||||
| 
 | ||||
| #endif //FFMPEGANDROID_FFPLAY_DEFINE_H
 | ||||
| @ -1,93 +0,0 @@ | ||||
| 
 | ||||
| #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); | ||||
|     } | ||||
| } | ||||
| @ -1,66 +0,0 @@ | ||||
| 
 | ||||
| #ifndef FFMPEGANDROID_FRAMEQUEUE_H | ||||
| #define FFMPEGANDROID_FRAMEQUEUE_H | ||||
| 
 | ||||
| #include <mutex> | ||||
| #include "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
 | ||||
| @ -1,142 +0,0 @@ | ||||
| 
 | ||||
| #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(); | ||||
| } | ||||
| @ -1,62 +0,0 @@ | ||||
| 
 | ||||
| #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
 | ||||
| Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 145 KiB | 
					Loading…
					
					
				
		Reference in new issue