AnyRTC project 音频解码成PCM裸数据的代码位置

2019-06-11 11:25:14 浏览数 (1)

该文件路径:C:DevtoolsprojectgitanyRTC-RTMP-OpenSourceAnyCoreplybuffer.cc

代码语言:javascript复制
/*
*  Copyright (c) 2016 The AnyRTC project authors. All Rights Reserved.
*
*  Please visit https://www.anyrtc.io for detail.
*
* The GNU General Public License is a free, copyleft license for
* software and other kinds of works.
*
* The licenses for most software and other practical works are designed
* to take away your freedom to share and change the works.  By contrast,
* the GNU General Public License is intended to guarantee your freedom to
* share and change all versions of a program--to make sure it remains free
* software for all its users.  We, the Free Software Foundation, use the
* GNU General Public License for most of our software; it applies also to
* any other work released this way by its authors.  You can apply it to
* your programs, too.
* See the GNU LICENSE file for more info.
*/
#include "plybuffer.h"
#include "webrtc/base/logging.h"

#define PLY_MIN_TIME    500     // 0.5s
#define PLY_MAX_TIME    600000      // 10minute
#define PLY_RED_TIME    250     // redundancy time
#define PLY_MAX_DELAY   1000        // 1 second
#define PLY_MAX_CACHE   160         // 16s

#define PB_TICK 1011

PlyBuffer::PlyBuffer(PlyBufferCallback&callback, rtc::Thread*worker)
    : callback_(callback)
    , worker_thread_(NULL)
    , got_audio_(false)
    , cache_time_(500)  // default 1000ms(1s)
    , cache_delta_(0)
    , buf_cache_time_(0)
    , ply_status_(PS_Fast)
    , sys_fast_video_time_(0)
    , rtmp_fast_video_time_(0)
    , rtmp_cache_time_(0)
    , play_cur_time_(0)
{
    ASSERT(worker != NULL);
    worker_thread_ = worker;
    worker_thread_->PostDelayed(RTC_FROM_HERE, 1, this, PB_TICK);
}


PlyBuffer::~PlyBuffer()
{
    std::list<PlyPacket*>::iterator iter = lst_audio_buffer_.begin();
    while (iter != lst_audio_buffer_.end()) {
        PlyPacket* pkt = *iter;
        lst_audio_buffer_.erase(iter  );
        delete pkt;
    }
    iter = lst_video_buffer_.begin();
    while (iter != lst_video_buffer_.end()) {
        PlyPacket* pkt = *iter;
        lst_video_buffer_.erase(iter  );
        delete pkt;
    }
}

void PlyBuffer::SetCacheSize(int miliseconds/*ms*/)
{
    if (miliseconds > 500 && miliseconds <= 600000) {   //* 0.5s ~ 10 minute
        cache_time_ = miliseconds;
    }
}
int PlyBuffer::GetPlayAudio(void* audioSamples)
{
    int ret = 0;
    rtc::CritScope cs(&cs_list_audio_);
    if (lst_audio_buffer_.size() > 0) {
        PlyPacket* pkt_front = lst_audio_buffer_.front();
        ret = pkt_front->_data_len;
        play_cur_time_ = pkt_front->_dts;
        
        memcpy(audioSamples, pkt_front->_data, pkt_front->_data_len);
        lst_audio_buffer_.pop_front();
        delete pkt_front;
    }

    return ret;
}
void PlyBuffer::CacheH264Data(const uint8_t*pdata, int len, uint32_t ts)
{
    PlyPacket* pkt = new PlyPacket(true);
    pkt->SetData(pdata, len, ts);
    if (sys_fast_video_time_ == 0)
    {
        sys_fast_video_time_ = rtc::Time();
        rtmp_fast_video_time_ = ts;
    }
    rtc::CritScope cs(&cs_list_video_);
    lst_video_buffer_.push_back(pkt);
}

void PlyBuffer::CachePcmData(const uint8_t*pdata, int len, uint32_t ts)
{
    PlyPacket* pkt = new PlyPacket(false);
    pkt->SetData(pdata, len, ts);
    rtc::CritScope cs(&cs_list_audio_);
    got_audio_ = true;
    lst_audio_buffer_.push_back(pkt);
    if (sys_fast_video_time_ == 0) {
        PlyPacket* pkt_front = lst_audio_buffer_.front();
        PlyPacket* pkt_back = lst_audio_buffer_.back();
        if ((pkt_back->_dts - pkt_front->_dts) >= PLY_MAX_DELAY) {
            sys_fast_video_time_ = rtc::Time();
            rtmp_fast_video_time_ = ts;
        }
    }
}

void PlyBuffer::OnMessage(rtc::Message* msg)
{
    if (msg->message_id == PB_TICK) {
        DoDecode();
        worker_thread_->PostDelayed(RTC_FROM_HERE, 5, this, PB_TICK);
    }
}

int PlyBuffer::GetCacheTime()
{
    return cache_time_;
}

void PlyBuffer::DoDecode()
{
    uint32_t curTime = rtc::Time();
    if (sys_fast_video_time_ == 0)
        return;
    if (ply_status_ == PS_Fast) {
        PlyPacket* pkt = NULL;
        uint32_t videoSysGap = curTime - sys_fast_video_time_;
        uint32_t videoPlyTime = rtmp_fast_video_time_   videoSysGap;
        if (videoSysGap >= PLY_RED_TIME) {
            //* Start play a/v
            rtc::CritScope cs(&cs_list_audio_);
            if (lst_audio_buffer_.size() > 0) {
                PlyPacket* pkt_front = lst_audio_buffer_.front();
                PlyPacket* pkt_back = lst_audio_buffer_.back();
                if ((pkt_back->_dts - pkt_front->_dts) > PLY_RED_TIME) {
                    ply_status_ = PS_Normal;
                    play_cur_time_ = pkt_front->_dts;
                    callback_.OnPlay();
                }
            }
            else {
                if (videoSysGap >= PLY_RED_TIME * 4)
                {
                    rtc::CritScope cs(&cs_list_video_);
                    if (lst_video_buffer_.size() > 0) {
                        PlyPacket* pkt_front = lst_video_buffer_.front();
                        ply_status_ = PS_Normal;
                        play_cur_time_ = pkt_front->_dts;
                        callback_.OnPlay();
                    }
                }
            }
        }
    }
    else if (ply_status_ == PS_Normal) {
        PlyPacket* pkt_video = NULL;
        uint32_t media_buf_time = 0;
        uint32_t play_video_time = play_cur_time_;
        {//* Get audio 
            rtc::CritScope cs(&cs_list_audio_);
            if (lst_audio_buffer_.size() > 0) {
                media_buf_time = lst_audio_buffer_.back()->_dts - lst_audio_buffer_.front()->_dts;
            }
        }
        if (media_buf_time == 0 && !got_audio_) {
            rtc::CritScope cs(&cs_list_video_);
            if (lst_video_buffer_.size() > 0) {
                media_buf_time = lst_video_buffer_.back()->_dts - lst_video_buffer_.front()->_dts;
                uint32_t videoSysGap = curTime - sys_fast_video_time_;
                play_video_time = rtmp_fast_video_time_   videoSysGap;
            }
        }
    
        {//* Get video 
            rtc::CritScope cs(&cs_list_video_);
            if (lst_video_buffer_.size() > 0) {
                pkt_video = lst_video_buffer_.front();
                if (pkt_video->_dts <= play_video_time) {
                    lst_video_buffer_.pop_front();
                    //LOG(LS_WARNING) << "play_cur_time_ " << play_cur_time_ << "tpkt_video->_dts " << pkt_video->_dts;
                }
                else {
                    pkt_video = NULL;
                }
            }
        }

        if (pkt_video) {
            if (!callback_.OnNeedDecodeData(pkt_video)) {
                delete pkt_video;
            }
        }

        if (media_buf_time <= PLY_RED_TIME) {
            // Play buffer is so small, then we need buffer it?
            callback_.OnPause();
            ply_status_ = PS_Cache;
            cache_time_ = cache_delta_ * 100;
            if(cache_delta_ < PLY_MAX_CACHE)
                cache_delta_ *= 2;
            rtmp_cache_time_ = rtc::Time()   cache_time_;
        }
        buf_cache_time_ = media_buf_time;
    }
    else if (ply_status_ == PS_Cache) {
        if (rtmp_cache_time_ <= rtc::Time()) {
            uint32_t media_buf_time = 0;
            {
                rtc::CritScope cs(&cs_list_audio_);
                if (lst_audio_buffer_.size() > 0) {
                    media_buf_time = lst_audio_buffer_.back()->_dts - lst_audio_buffer_.front()->_dts;
                    LOG(LS_WARNING) << "media_buf_time " << media_buf_time;
                }
            }
            if (media_buf_time == 0 && !got_audio_) {
                rtc::CritScope cs(&cs_list_video_);
                if (lst_video_buffer_.size() > 0) {
                    media_buf_time = lst_video_buffer_.back()->_dts - lst_video_buffer_.front()->_dts;
                }
            }

            int cache_time_ts = cache_time_ - PLY_RED_TIME;
            if (cache_time_ts < 0) cache_time_ts = 0;

            if (media_buf_time >= cache_time_ts) {
                ply_status_ = PS_Normal;
                if (cache_delta_ == PLY_MAX_CACHE)
                    cache_delta_ /= 2;
                callback_.OnPlay();
            }
            else {
                rtmp_cache_time_ = rtc::Time()   cache_time_;
            }
            if (!got_audio_) {
                sys_fast_video_time_  = cache_time_;
            }
            buf_cache_time_ = media_buf_time;
        }
    }
}

0 人点赞