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