diff --git a/README.md b/README.md index 5293e7b..00fed36 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,9 @@ WebRTC设计传输协议有SDP、SRTP、ICE、NAT、STUN等,常用视频编码 ### 音视频开源库: ![preview](https://github.com/xufuji456/FFmpegAndroid/blob/master/picture/multimedia_library.png) +### 音视频教程: +[一起学习音视频](https://ke.qq.com/course/5613182#term_id=105809583) + ### Joining the group to learn FFmpeg: ![preview](https://github.com/xufuji456/FFmpegAndroid/blob/master/picture/ffmpeg_group.png) diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index ce5e9ae..f940916 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -32,18 +32,7 @@ set(SRC_METADATA metadata/metadata_util.c metadata/ffmpeg_media_retriever.c) -set(SRC_FFPLAYER - ffplayer/queue/FrameQueue.cpp - ffplayer/queue/PacketQueue.cpp - ffplayer/decode/BaseDecoder.cpp - ffplayer/decode/FFAudioDecoder.cpp - ffplayer/decode/FFVideoDecoder.cpp - ffplayer/clock/MediaClock.cpp - ffplayer/clock/AVSync.cpp - ffplayer/render/AudioRender.cpp - ffplayer/ff_mediaplayer_jni.cpp - ffplayer/FFMessageQueue.cpp - ffplayer/FFMediaPlayer.cpp) +set(SRC_FFPLAYER ffplayer) add_library( # Sets the name of the library. media-handle diff --git a/app/src/main/cpp/ffplayer/FFMessageQueue.cpp b/app/src/main/cpp/ffplayer/FFMessageQueue.cpp deleted file mode 100644 index 3999402..0000000 --- a/app/src/main/cpp/ffplayer/FFMessageQueue.cpp +++ /dev/null @@ -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(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 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 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 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 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 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 lock(q->mutex); - q->abort_request = 1; - q->cond.notify_all(); -} - -void FFMessageQueue::destroy() { - flush(); - std::lock_guard 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); - } -} \ No newline at end of file diff --git a/app/src/main/cpp/ffplayer/FFMessageQueue.h b/app/src/main/cpp/ffplayer/FFMessageQueue.h deleted file mode 100644 index bad8e28..0000000 --- a/app/src/main/cpp/ffplayer/FFMessageQueue.h +++ /dev/null @@ -1,96 +0,0 @@ - -#ifndef FFMPEGANDROID_FFMESSAGEQUEUE_H -#define FFMPEGANDROID_FFMESSAGEQUEUE_H - -#include -#include - -/**************** 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 diff --git a/app/src/main/cpp/ffplayer/clock/MediaClock.cpp b/app/src/main/cpp/ffplayer/clock/MediaClock.cpp deleted file mode 100644 index dce88ac..0000000 --- a/app/src/main/cpp/ffplayer/clock/MediaClock.cpp +++ /dev/null @@ -1,50 +0,0 @@ - -#include -#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() { - -} \ No newline at end of file diff --git a/app/src/main/cpp/ffplayer/clock/MediaClock.h b/app/src/main/cpp/ffplayer/clock/MediaClock.h deleted file mode 100644 index 0b1df8b..0000000 --- a/app/src/main/cpp/ffplayer/clock/MediaClock.h +++ /dev/null @@ -1,45 +0,0 @@ - -#ifndef FFMPEGANDROID_MEDIACLOCK_H -#define FFMPEGANDROID_MEDIACLOCK_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif -#include -#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 diff --git a/app/src/main/cpp/ffplayer/ffplay_define.h b/app/src/main/cpp/ffplayer/ffplay_define.h deleted file mode 100644 index 90968f4..0000000 --- a/app/src/main/cpp/ffplayer/ffplay_define.h +++ /dev/null @@ -1,98 +0,0 @@ - -#ifndef FFMPEGANDROID_FFPLAY_DEFINE_H -#define FFMPEGANDROID_FFPLAY_DEFINE_H - -#include -#include "FFMessageQueue.h" - -#ifdef __cplusplus -extern "C" { -#endif -#include -#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 diff --git a/app/src/main/cpp/ffplayer/queue/FrameQueue.cpp b/app/src/main/cpp/ffplayer/queue/FrameQueue.cpp deleted file mode 100644 index 75b1ee1..0000000 --- a/app/src/main/cpp/ffplayer/queue/FrameQueue.cpp +++ /dev/null @@ -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 lock(m_mutex); - m_abort_request = 0; -} - -void FrameQueue::abort() { - std::lock_guard 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 lock(m_mutex); - if (++m_write_idx == m_max_size) { - m_write_idx = 0; - } - m_size++; -} - -void FrameQueue::popFrame() { - std::unique_lock 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); - } -} \ No newline at end of file diff --git a/app/src/main/cpp/ffplayer/queue/FrameQueue.h b/app/src/main/cpp/ffplayer/queue/FrameQueue.h deleted file mode 100644 index 5b53451..0000000 --- a/app/src/main/cpp/ffplayer/queue/FrameQueue.h +++ /dev/null @@ -1,66 +0,0 @@ - -#ifndef FFMPEGANDROID_FRAMEQUEUE_H -#define FFMPEGANDROID_FRAMEQUEUE_H - -#include -#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 diff --git a/app/src/main/cpp/ffplayer/queue/PacketQueue.cpp b/app/src/main/cpp/ffplayer/queue/PacketQueue.cpp deleted file mode 100644 index b1d9db1..0000000 --- a/app/src/main/cpp/ffplayer/queue/PacketQueue.cpp +++ /dev/null @@ -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 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 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 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 lock(m_mutex); - m_abort_request = 0; -} - -void PacketQueue::abort() { - std::lock_guard lock(m_mutex); - m_abort_request = 1; -} - -int PacketQueue::getSize() { - std::lock_guard lock(m_mutex); - return m_size; -} - -int PacketQueue::getPacketSize() { - std::lock_guard 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(); -} \ No newline at end of file diff --git a/app/src/main/cpp/ffplayer/queue/PacketQueue.h b/app/src/main/cpp/ffplayer/queue/PacketQueue.h deleted file mode 100644 index 23973cf..0000000 --- a/app/src/main/cpp/ffplayer/queue/PacketQueue.h +++ /dev/null @@ -1,62 +0,0 @@ - -#ifndef FFMPEGANDROID_PACKETQUEUE_H -#define FFMPEGANDROID_PACKETQUEUE_H - - -#include -#include - -extern "C" { -#include -} - -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 diff --git a/picture/ffmpeg_group.png b/picture/ffmpeg_group.png index f72c75e..4b137a5 100644 Binary files a/picture/ffmpeg_group.png and b/picture/ffmpeg_group.png differ