LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/common_audio - ring_buffer.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 111 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
       3             :  *
       4             :  *  Use of this source code is governed by a BSD-style license
       5             :  *  that can be found in the LICENSE file in the root of the source
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS.  All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  */
      10             : 
      11             : // A ring buffer to hold arbitrary data. Provides no thread safety. Unless
      12             : // otherwise specified, functions return 0 on success and -1 on error.
      13             : 
      14             : #include "webrtc/common_audio/ring_buffer.h"
      15             : 
      16             : #include <stddef.h>  // size_t
      17             : #include <stdlib.h>
      18             : #include <string.h>
      19             : 
      20             : // Get address of region(s) from which we can read data.
      21             : // If the region is contiguous, |data_ptr_bytes_2| will be zero.
      22             : // If non-contiguous, |data_ptr_bytes_2| will be the size in bytes of the second
      23             : // region. Returns room available to be read or |element_count|, whichever is
      24             : // smaller.
      25           0 : static size_t GetBufferReadRegions(RingBuffer* buf,
      26             :                                    size_t element_count,
      27             :                                    void** data_ptr_1,
      28             :                                    size_t* data_ptr_bytes_1,
      29             :                                    void** data_ptr_2,
      30             :                                    size_t* data_ptr_bytes_2) {
      31             : 
      32           0 :   const size_t readable_elements = WebRtc_available_read(buf);
      33           0 :   const size_t read_elements = (readable_elements < element_count ?
      34             :       readable_elements : element_count);
      35           0 :   const size_t margin = buf->element_count - buf->read_pos;
      36             : 
      37             :   // Check to see if read is not contiguous.
      38           0 :   if (read_elements > margin) {
      39             :     // Write data in two blocks that wrap the buffer.
      40           0 :     *data_ptr_1 = buf->data + buf->read_pos * buf->element_size;
      41           0 :     *data_ptr_bytes_1 = margin * buf->element_size;
      42           0 :     *data_ptr_2 = buf->data;
      43           0 :     *data_ptr_bytes_2 = (read_elements - margin) * buf->element_size;
      44             :   } else {
      45           0 :     *data_ptr_1 = buf->data + buf->read_pos * buf->element_size;
      46           0 :     *data_ptr_bytes_1 = read_elements * buf->element_size;
      47           0 :     *data_ptr_2 = NULL;
      48           0 :     *data_ptr_bytes_2 = 0;
      49             :   }
      50             : 
      51           0 :   return read_elements;
      52             : }
      53             : 
      54           0 : RingBuffer* WebRtc_CreateBuffer(size_t element_count, size_t element_size) {
      55           0 :   RingBuffer* self = NULL;
      56           0 :   if (element_count == 0 || element_size == 0) {
      57           0 :     return NULL;
      58             :   }
      59             : 
      60           0 :   self = malloc(sizeof(RingBuffer));
      61           0 :   if (!self) {
      62           0 :     return NULL;
      63             :   }
      64             : 
      65           0 :   self->data = malloc(element_count * element_size);
      66           0 :   if (!self->data) {
      67           0 :     free(self);
      68           0 :     self = NULL;
      69           0 :     return NULL;
      70             :   }
      71             : 
      72           0 :   self->element_count = element_count;
      73           0 :   self->element_size = element_size;
      74           0 :   WebRtc_InitBuffer(self);
      75             : 
      76           0 :   return self;
      77             : }
      78             : 
      79           0 : void WebRtc_InitBuffer(RingBuffer* self) {
      80           0 :   self->read_pos = 0;
      81           0 :   self->write_pos = 0;
      82           0 :   self->rw_wrap = SAME_WRAP;
      83             : 
      84             :   // Initialize buffer to zeros
      85           0 :   memset(self->data, 0, self->element_count * self->element_size);
      86           0 : }
      87             : 
      88           0 : void WebRtc_FreeBuffer(void* handle) {
      89           0 :   RingBuffer* self = (RingBuffer*)handle;
      90           0 :   if (!self) {
      91           0 :     return;
      92             :   }
      93             : 
      94           0 :   free(self->data);
      95           0 :   free(self);
      96             : }
      97             : 
      98           0 : size_t WebRtc_ReadBuffer(RingBuffer* self,
      99             :                          void** data_ptr,
     100             :                          void* data,
     101             :                          size_t element_count) {
     102             : 
     103           0 :   if (self == NULL) {
     104           0 :     return 0;
     105             :   }
     106           0 :   if (data == NULL) {
     107           0 :     return 0;
     108             :   }
     109             : 
     110             :   {
     111           0 :     void* buf_ptr_1 = NULL;
     112           0 :     void* buf_ptr_2 = NULL;
     113           0 :     size_t buf_ptr_bytes_1 = 0;
     114           0 :     size_t buf_ptr_bytes_2 = 0;
     115           0 :     const size_t read_count = GetBufferReadRegions(self,
     116             :                                                    element_count,
     117             :                                                    &buf_ptr_1,
     118             :                                                    &buf_ptr_bytes_1,
     119             :                                                    &buf_ptr_2,
     120             :                                                    &buf_ptr_bytes_2);
     121             : 
     122           0 :     if (buf_ptr_bytes_2 > 0) {
     123             :       // We have a wrap around when reading the buffer. Copy the buffer data to
     124             :       // |data| and point to it.
     125           0 :       memcpy(data, buf_ptr_1, buf_ptr_bytes_1);
     126           0 :       memcpy(((char*) data) + buf_ptr_bytes_1, buf_ptr_2, buf_ptr_bytes_2);
     127           0 :       buf_ptr_1 = data;
     128           0 :     } else if (!data_ptr) {
     129             :       // No wrap, but a memcpy was requested.
     130           0 :       memcpy(data, buf_ptr_1, buf_ptr_bytes_1);
     131             :     }
     132           0 :     if (data_ptr) {
     133             :       // |buf_ptr_1| == |data| in the case of a wrap.
     134           0 :       *data_ptr = buf_ptr_1;
     135             :     }
     136             : 
     137             :     // Update read position
     138           0 :     WebRtc_MoveReadPtr(self, (int) read_count);
     139             : 
     140           0 :     return read_count;
     141             :   }
     142             : }
     143             : 
     144           0 : size_t WebRtc_WriteBuffer(RingBuffer* self,
     145             :                           const void* data,
     146             :                           size_t element_count) {
     147           0 :   if (!self) {
     148           0 :     return 0;
     149             :   }
     150           0 :   if (!data) {
     151           0 :     return 0;
     152             :   }
     153             : 
     154             :   {
     155           0 :     const size_t free_elements = WebRtc_available_write(self);
     156           0 :     const size_t write_elements = (free_elements < element_count ? free_elements
     157             :         : element_count);
     158           0 :     size_t n = write_elements;
     159           0 :     const size_t margin = self->element_count - self->write_pos;
     160             : 
     161           0 :     if (write_elements > margin) {
     162             :       // Buffer wrap around when writing.
     163           0 :       memcpy(self->data + self->write_pos * self->element_size,
     164           0 :              data, margin * self->element_size);
     165           0 :       self->write_pos = 0;
     166           0 :       n -= margin;
     167           0 :       self->rw_wrap = DIFF_WRAP;
     168             :     }
     169           0 :     memcpy(self->data + self->write_pos * self->element_size,
     170           0 :            ((const char*) data) + ((write_elements - n) * self->element_size),
     171           0 :            n * self->element_size);
     172           0 :     self->write_pos += n;
     173             : 
     174           0 :     return write_elements;
     175             :   }
     176             : }
     177             : 
     178           0 : int WebRtc_MoveReadPtr(RingBuffer* self, int element_count) {
     179           0 :   if (!self) {
     180           0 :     return 0;
     181             :   }
     182             : 
     183             :   {
     184             :     // We need to be able to take care of negative changes, hence use "int"
     185             :     // instead of "size_t".
     186           0 :     const int free_elements = (int) WebRtc_available_write(self);
     187           0 :     const int readable_elements = (int) WebRtc_available_read(self);
     188           0 :     int read_pos = (int) self->read_pos;
     189             : 
     190           0 :     if (element_count > readable_elements) {
     191           0 :       element_count = readable_elements;
     192             :     }
     193           0 :     if (element_count < -free_elements) {
     194           0 :       element_count = -free_elements;
     195             :     }
     196             : 
     197           0 :     read_pos += element_count;
     198           0 :     if (read_pos > (int) self->element_count) {
     199             :       // Buffer wrap around. Restart read position and wrap indicator.
     200           0 :       read_pos -= (int) self->element_count;
     201           0 :       self->rw_wrap = SAME_WRAP;
     202             :     }
     203           0 :     if (read_pos < 0) {
     204             :       // Buffer wrap around. Restart read position and wrap indicator.
     205           0 :       read_pos += (int) self->element_count;
     206           0 :       self->rw_wrap = DIFF_WRAP;
     207             :     }
     208             : 
     209           0 :     self->read_pos = (size_t) read_pos;
     210             : 
     211           0 :     return element_count;
     212             :   }
     213             : }
     214             : 
     215           0 : size_t WebRtc_available_read(const RingBuffer* self) {
     216           0 :   if (!self) {
     217           0 :     return 0;
     218             :   }
     219             : 
     220           0 :   if (self->rw_wrap == SAME_WRAP) {
     221           0 :     return self->write_pos - self->read_pos;
     222             :   } else {
     223           0 :     return self->element_count - self->read_pos + self->write_pos;
     224             :   }
     225             : }
     226             : 
     227           0 : size_t WebRtc_available_write(const RingBuffer* self) {
     228           0 :   if (!self) {
     229           0 :     return 0;
     230             :   }
     231             : 
     232           0 :   return self->element_count - WebRtc_available_read(self);
     233             : }

Generated by: LCOV version 1.13