前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >AnyRTC project 音频解码成PCM裸数据的代码位置

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

作者头像
xiny120
发布2019-06-11 11:25:14
6160
发布2019-06-11 11:25:14
举报
文章被收录于专栏:毛毛v5毛毛v5

该文件路径:C:\Devtools\project\git\anyRTC-RTMP-OpenSource\AnyCore\plybuffer.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;
        }
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.04.09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档