<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          音視頻環(huán)形緩沖區(qū) 介紹與實(shí)現(xiàn)

          共 8157字,需瀏覽 17分鐘

           ·

          2022-07-24 13:01

          一、什么是環(huán)形緩沖區(qū)

          環(huán)形緩沖區(qū)(也稱為循環(huán)緩沖區(qū))是固定大小的緩沖區(qū),工作原理就像內(nèi)存是連續(xù)的且可循環(huán)的一樣。在生成和使用內(nèi)存時(shí),不需將原來(lái)的數(shù)據(jù)全部重新清理掉,只要調(diào)整head/tail 指針即可。當(dāng)添加數(shù)據(jù)時(shí),head 指針前進(jìn)。當(dāng)使用數(shù)據(jù)時(shí),tail 指針向前移動(dòng)。當(dāng)?shù)竭_(dá)緩沖區(qū)的尾部時(shí),指針又回到緩沖區(qū)的起始位置。

          二、為什么使用環(huán)形緩沖區(qū)

          環(huán)形緩沖區(qū)是嵌入式系統(tǒng)中十分重要的一種數(shù)據(jù)結(jié)構(gòu),比如在一個(gè)音視頻處理的機(jī)制中,環(huán)形緩沖區(qū)就可以理解為數(shù)據(jù)碼流的通道,每一個(gè)通道都對(duì)應(yīng)著一個(gè)環(huán)形緩沖區(qū),這樣數(shù)據(jù)在讀取和寫入的時(shí)候都可以在這個(gè)緩沖區(qū)里循環(huán)進(jìn)行,程序員可以根據(jù)自己需要的數(shù)據(jù)大小來(lái)決定自己使用的緩沖區(qū)大小。

          環(huán)形緩沖區(qū)通常用作固定大小的隊(duì)列。固定大小的隊(duì)列對(duì)于嵌入式系統(tǒng)的開(kāi)發(fā)非常友好,因?yàn)殚_(kāi)發(fā)人員通常會(huì)嘗試使用靜態(tài)數(shù)據(jù)存儲(chǔ)的方法而不是動(dòng)態(tài)分配。

          環(huán)形緩沖區(qū)對(duì)于數(shù)據(jù)寫入和讀出以不同速率發(fā)生的情況也是非常有用的結(jié)構(gòu):最新數(shù)據(jù)始終可用。如果讀取數(shù)據(jù)的速度跟不上寫入數(shù)據(jù)的速度,舊的數(shù)據(jù)將被新寫入的數(shù)據(jù)覆蓋。通過(guò)使用循環(huán)緩沖區(qū),能夠保證我們始終使用最新的數(shù)據(jù)。

          三、代碼實(shí)現(xiàn)

          1. 環(huán)形緩存區(qū)結(jié)構(gòu)體RING_BUFFER

          typedef struct
          {

              //緩存空間指針
              char*                           buffer;
              //緩存空間容量
              int                             size;
              //緩存讀序號(hào),范圍:0 - (size -1)
              int                             rdIdx;
              //緩存寫序號(hào),范圍:0 - (size -1)
              int                             wrIdx;
              //緩存滿標(biāo)志
              int                             isFull;
          }RING_BUFFER;

          2. 創(chuàng)建環(huán)形緩存區(qū)

          voidringBufferCreate(int size)
          {
              RING_BUFFER*    rb;
              if(NULL == (rb = malloc(sizeof(RING_BUFFER) + size)))
              {
                  printf("內(nèi)存不足!\n");
                  return NULL;
              }
              memset(rb, 0sizeof(RING_BUFFER));
              rb->buffer = (char*)rb + sizeof(RING_BUFFER);
              rb->size = size;
              return (void*)rb;
          }

          3. 獲取環(huán)形緩存區(qū)中有效數(shù)據(jù)大小

          int ringBufferGetSize(RING_BUFFER* rb)
          {
              if(rb->wrIdx == rb->rdIdx)
              {
                  return 0;
              }
              if(rb->wrIdx > rb->rdIdx)
              {
                  return (rb->wrIdx - rb->rdIdx);
              }
              return ((rb->size - rb->rdIdx) + rb->wrIdx);
          }

          4. 獲取環(huán)形緩存區(qū)中空閑空間字節(jié)大小

          int ringBufferFreeLen(RING_BUFFER* rb)
          {
              return ((rb->size - 1) - __ringBufferGetSize(rb));
          }

          5. 寫環(huán)形緩存區(qū)

          int ringBufferWrite(void* handle, const char* ptr, int len)
          {
              RING_BUFFER*    rb = (void*)handle;
              int          size;
              if(0 >= len)
              {
                  printf("rb寫參數(shù)[%lu]非法!\n", len);
                  return 0;
              }
              //獲取空閑空間大小
              size = ringBufferFreeLen(rb);
              if(size < len)
              {
                  //空閑空間不足
                  printf("rb寫溢出!<%d, %d>\n", len, size);
                  return 0;
              }
              //計(jì)算"寫序號(hào)"后部還允許寫入的數(shù)據(jù)字節(jié)數(shù)
              size = rb->size - rb->wrIdx;
              if(size >= len)
              {
                  //當(dāng)前待寫入全部數(shù)據(jù)可一次寫入后部
                  memcpy(rb->buffer + rb->wrIdx, ptr, len);
                  rb->wrIdx = (size > len) ? (rb->wrIdx + len) : 0;
                  return len;
              }
              //先寫一部分?jǐn)?shù)據(jù)到后部
              memcpy(rb->buffer + rb->wrIdx, ptr, size);
              //再寫剩余數(shù)據(jù)到前部
              memcpy(rb->buffer, ptr + size, len - size);
              rb->wrIdx = len - size;
              return len;
          }

          6. 讀環(huán)形緩存區(qū)

          int ringBufferRead(void* handle, char* ptr, int len)
          {
              RING_BUFFER*    rb = (void*)handle;
              int         size;
              if(0 >= len)
              {
                  printf("rb讀參數(shù)[%lu]非法!\n", len);
                  return 0;
              }
              //獲取有效數(shù)據(jù)大小
              size = ringBufferGetSize(rb);
              if(0 == size)
              {
                  return 0;//沒(méi)有數(shù)據(jù)
              }
              if(0 != rb->isFull)
              {
                  //之前已標(biāo)記 緩存滿,全清 緩存內(nèi)容
                  rb->rdIdx = rb->wrIdx;
                  rb->isFull = 0;
                  return 0;
              }
              if(size < len)
              {
                  //有效數(shù)據(jù)不足,只能返回填充一部分
                  len = size;
              }
              //計(jì)算"讀序號(hào)"后部可讀空間大小
              size = rb->size - rb->rdIdx;
              if(size >= len)
              {
                  //當(dāng)前待讀出全部數(shù)據(jù)全存在于"讀序號(hào)"后部
                  memcpy(ptr, rb->buffer + rb->rdIdx, len);
                  rb->rdIdx = (size > len) ? (rb->rdIdx + len) : 0;
                  return len;
              }
              //先從"讀序號(hào)"后部讀出一部分?jǐn)?shù)據(jù)
              memcpy(ptr, rb->buffer + rb->rdIdx, size);
              //再?gòu)那安孔x出剩余數(shù)據(jù)
              memcpy(ptr + size, rb->buffer, len - size);
              rb->rdIdx = len - size;
              return len;
          }

          7. 銷毀環(huán)形緩存區(qū)

          int ringBufferDestroy(void* handle)
          {
              RING_BUFFER*    rb = (void*)handle;
              ctFree(rb);
              return 0;
          }
          來(lái)源:https://blog.csdn.net/u012478275/article/details/122101925

          最后歡迎大家加入 音視頻開(kāi)發(fā)進(jìn)階 知識(shí)星球 ,這里有知識(shí)干貨、編程答疑、開(kāi)發(fā)教程,還有很多精彩分享。


          更多內(nèi)容可以在星球菜單中找到,隨著時(shí)間推移,干貨也會(huì)越來(lái)越多?。。?/span>


          給出 10元 優(yōu)惠券,漲價(jià)在即,目前還是白菜價(jià),基本上提幾個(gè)問(wèn)題就回本,投資自己就是最好的投資?。?!


          加我微信 ezglumes ,拉你進(jìn)技術(shù)交流群

          推薦閱讀:

          音視頻開(kāi)發(fā)工作經(jīng)驗(yàn)分享 || 視頻版

          OpenGL ES 學(xué)習(xí)資源分享

          開(kāi)通專輯 | 細(xì)數(shù)那些年寫過(guò)的技術(shù)文章專輯

          Android NDK 免費(fèi)視頻在線學(xué)習(xí)?。?!

          你想要的音視頻開(kāi)發(fā)資料庫(kù)來(lái)了

          推薦幾個(gè)堪稱教科書級(jí)別的 Android 音視頻入門項(xiàng)目

          覺(jué)得不錯(cuò),點(diǎn)個(gè)在看唄~

          瀏覽 57
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人毛片在线观看 | 一级黄片乱伦 | 日本国产在线观看 | 国产女人18毛片水18精 | 青娱乐自拍区 |