⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jitter.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 2 页
字号:
         int earliest=jitter->packets[0].timestamp;         i=0;         for (j=1;j<SPEEX_JITTER_MAX_BUFFER_SIZE;j++)         {            if (!jitter->packets[i].data || LT32(jitter->packets[j].timestamp,earliest))            {               earliest = jitter->packets[j].timestamp;               i=j;            }         }         if (jitter->destroy)            jitter->destroy(jitter->packets[i].data);         else            speex_free(jitter->packets[i].data);         jitter->packets[i].data=NULL;         /*fprintf (stderr, "Buffer is full, discarding earliest frame %d (currently at %d)\n", timestamp, jitter->pointer_timestamp);*/            }         /* Copy packet in buffer */      if (jitter->destroy)      {         jitter->packets[i].data = packet->data;      } else {         jitter->packets[i].data=(char*)speex_alloc(packet->len);         for (j=0;j<packet->len;j++)            jitter->packets[i].data[j]=packet->data[j];      }      jitter->packets[i].timestamp=packet->timestamp;      jitter->packets[i].span=packet->span;      jitter->packets[i].len=packet->len;      jitter->packets[i].sequence=packet->sequence;      jitter->packets[i].user_data=packet->user_data;      if (jitter->reset_state || late)         jitter->arrival[i] = 0;      else         jitter->arrival[i] = jitter->next_stop;   }      }/** Get one packet from the jitter buffer */EXPORT int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset){   int i;   unsigned int j;   int incomplete = 0;   spx_int16_t opt;      if (start_offset != NULL)      *start_offset = 0;   /* Syncing on the first call */   if (jitter->reset_state)   {      int found = 0;      /* Find the oldest packet */      spx_uint32_t oldest=0;      for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)      {         if (jitter->packets[i].data && (!found || LT32(jitter->packets[i].timestamp,oldest)))         {            oldest = jitter->packets[i].timestamp;            found = 1;         }      }      if (found)      {         jitter->reset_state=0;                  jitter->pointer_timestamp = oldest;         jitter->next_stop = oldest;      } else {         packet->timestamp = 0;         packet->span = jitter->interp_requested;         return JITTER_BUFFER_MISSING;      }   }      jitter->last_returned_timestamp = jitter->pointer_timestamp;            if (jitter->interp_requested != 0)   {      packet->timestamp = jitter->pointer_timestamp;      packet->span = jitter->interp_requested;            /* Increment the pointer because it got decremented in the delay update */      jitter->pointer_timestamp += jitter->interp_requested;      packet->len = 0;      /*fprintf (stderr, "Deferred interpolate\n");*/            jitter->interp_requested = 0;            jitter->buffered = packet->span - desired_span;      return JITTER_BUFFER_INSERTION;   }      /* Searching for the packet that fits best */      /* Search the buffer for a packet with the right timestamp and spanning the whole current chunk */   for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)   {      if (jitter->packets[i].data && jitter->packets[i].timestamp==jitter->pointer_timestamp && GE32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp+desired_span))         break;   }      /* If no match, try for an "older" packet that still spans (fully) the current chunk */   if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)   {      for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)      {         if (jitter->packets[i].data && LE32(jitter->packets[i].timestamp, jitter->pointer_timestamp) && GE32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp+desired_span))            break;      }   }      /* If still no match, try for an "older" packet that spans part of the current chunk */   if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)   {      for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)      {         if (jitter->packets[i].data && LE32(jitter->packets[i].timestamp, jitter->pointer_timestamp) && GT32(jitter->packets[i].timestamp+jitter->packets[i].span,jitter->pointer_timestamp))            break;      }   }      /* If still no match, try for earliest packet possible */   if (i==SPEEX_JITTER_MAX_BUFFER_SIZE)   {      int found = 0;      spx_uint32_t best_time=0;      int best_span=0;      int besti=0;      for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)      {         /* check if packet starts within current chunk */         if (jitter->packets[i].data && LT32(jitter->packets[i].timestamp,jitter->pointer_timestamp+desired_span) && GE32(jitter->packets[i].timestamp,jitter->pointer_timestamp))         {            if (!found || LT32(jitter->packets[i].timestamp,best_time) || (jitter->packets[i].timestamp==best_time && GT32(jitter->packets[i].span,best_span)))            {               best_time = jitter->packets[i].timestamp;               best_span = jitter->packets[i].span;               besti = i;               found = 1;            }         }      }      if (found)      {         i=besti;         incomplete = 1;         /*fprintf (stderr, "incomplete: %d %d %d %d\n", jitter->packets[i].timestamp, jitter->pointer_timestamp, chunk_size, jitter->packets[i].span);*/      }   }   /* If we find something */   if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE)   {      spx_int32_t offset;            /* We (obviously) haven't lost this packet */      jitter->lost_count = 0;            /* In this case, 0 isn't as a valid timestamp */      if (jitter->arrival[i] != 0)      {         update_timings(jitter, ((spx_int32_t)jitter->packets[i].timestamp) - ((spx_int32_t)jitter->arrival[i]) - jitter->buffer_margin);      }                  /* Copy packet */      if (jitter->destroy)      {         packet->data = jitter->packets[i].data;         packet->len = jitter->packets[i].len;      } else {         if (jitter->packets[i].len > packet->len)         {            speex_warning_int("jitter_buffer_get(): packet too large to fit. Size is", jitter->packets[i].len);         } else {            packet->len = jitter->packets[i].len;         }         for (j=0;j<packet->len;j++)            packet->data[j] = jitter->packets[i].data[j];         /* Remove packet */         speex_free(jitter->packets[i].data);      }      jitter->packets[i].data = NULL;      /* Set timestamp and span (if requested) */      offset = (spx_int32_t)jitter->packets[i].timestamp-(spx_int32_t)jitter->pointer_timestamp;      if (start_offset != NULL)         *start_offset = offset;      else if (offset != 0)         speex_warning_int("jitter_buffer_get() discarding non-zero start_offset", offset);            packet->timestamp = jitter->packets[i].timestamp;      jitter->last_returned_timestamp = packet->timestamp;            packet->span = jitter->packets[i].span;      packet->sequence = jitter->packets[i].sequence;      packet->user_data = jitter->packets[i].user_data;      /* Point to the end of the current packet */      jitter->pointer_timestamp = jitter->packets[i].timestamp+jitter->packets[i].span;      jitter->buffered = packet->span - desired_span;            if (start_offset != NULL)         jitter->buffered += *start_offset;            return JITTER_BUFFER_OK;   }         /* If we haven't found anything worth returning */      /*fprintf (stderr, "not found\n");*/   jitter->lost_count++;   /*fprintf (stderr, "m");*/   /*fprintf (stderr, "lost_count = %d\n", jitter->lost_count);*/      opt = compute_opt_delay(jitter);      /* Should we force an increase in the buffer or just do normal interpolation? */      if (opt < 0)   {      /* Need to increase buffering */            /* Shift histogram to compensate */      shift_timings(jitter, -opt);            packet->timestamp = jitter->pointer_timestamp;      packet->span = -opt;      /* Don't move the pointer_timestamp forward */      packet->len = 0;            jitter->buffered = packet->span - desired_span;      return JITTER_BUFFER_INSERTION;      /*jitter->pointer_timestamp -= jitter->delay_step;*/      /*fprintf (stderr, "Forced to interpolate\n");*/   } else {      /* Normal packet loss */      packet->timestamp = jitter->pointer_timestamp;            desired_span = ROUND_DOWN(desired_span, jitter->concealment_size);      packet->span = desired_span;      jitter->pointer_timestamp += desired_span;      packet->len = 0;            jitter->buffered = packet->span - desired_span;      return JITTER_BUFFER_MISSING;      /*fprintf (stderr, "Normal loss\n");*/   }}EXPORT int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet){   int i, j;   for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)   {      if (jitter->packets[i].data && jitter->packets[i].timestamp==jitter->last_returned_timestamp)         break;   }   if (i!=SPEEX_JITTER_MAX_BUFFER_SIZE)   {      /* Copy packet */      packet->len = jitter->packets[i].len;      if (jitter->destroy)      {         packet->data = jitter->packets[i].data;      } else {         for (j=0;j<packet->len;j++)            packet->data[j] = jitter->packets[i].data[j];         /* Remove packet */         speex_free(jitter->packets[i].data);      }      jitter->packets[i].data = NULL;      packet->timestamp = jitter->packets[i].timestamp;      packet->span = jitter->packets[i].span;      packet->sequence = jitter->packets[i].sequence;      packet->user_data = jitter->packets[i].user_data;      return JITTER_BUFFER_OK;   } else {      packet->data = NULL;      packet->len = 0;      packet->span = 0;      return JITTER_BUFFER_MISSING;   }}/* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */static int _jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset){   spx_int16_t opt = compute_opt_delay(jitter);   /*fprintf(stderr, "opt adjustment is %d ", opt);*/      if (opt < 0)   {      shift_timings(jitter, -opt);            jitter->pointer_timestamp += opt;      jitter->interp_requested = -opt;      /*fprintf (stderr, "Decision to interpolate %d samples\n", -opt);*/   } else if (opt > 0)   {      shift_timings(jitter, -opt);      jitter->pointer_timestamp += opt;      /*fprintf (stderr, "Decision to drop %d samples\n", opt);*/   }      return opt;}/* Let the jitter buffer know it's the right time to adjust the buffering delay to the network conditions */EXPORT int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset){   /* If the programmer calls jitter_buffer_update_delay() directly,       automatically disable auto-adjustment */   jitter->auto_adjust = 0;   return _jitter_buffer_update_delay(jitter, packet, start_offset);}/** Get pointer timestamp of jitter buffer */EXPORT int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter){   return jitter->pointer_timestamp;}EXPORT void jitter_buffer_tick(JitterBuffer *jitter){   /* Automatically-adjust the buffering delay if requested */   if (jitter->auto_adjust)      _jitter_buffer_update_delay(jitter, NULL, NULL);      if (jitter->buffered >= 0)   {      jitter->next_stop = jitter->pointer_timestamp - jitter->buffered;   } else {      jitter->next_stop = jitter->pointer_timestamp;      speex_warning_int("jitter buffer sees negative buffering, your code might be broken. Value is ", jitter->buffered);   }   jitter->buffered = 0;}EXPORT void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem){   /* Automatically-adjust the buffering delay if requested */   if (jitter->auto_adjust)      _jitter_buffer_update_delay(jitter, NULL, NULL);      if (jitter->buffered < 0)      speex_warning_int("jitter buffer sees negative buffering, your code might be broken. Value is ", jitter->buffered);   jitter->next_stop = jitter->pointer_timestamp - rem;}/* Used like the ioctl function to control the jitter buffer parameters */EXPORT int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr){   int count, i;   switch(request)   {      case JITTER_BUFFER_SET_MARGIN:         jitter->buffer_margin = *(spx_int32_t*)ptr;         break;      case JITTER_BUFFER_GET_MARGIN:         *(spx_int32_t*)ptr = jitter->buffer_margin;         break;      case JITTER_BUFFER_GET_AVALIABLE_COUNT:         count = 0;         for (i=0;i<SPEEX_JITTER_MAX_BUFFER_SIZE;i++)         {            if (jitter->packets[i].data && LE32(jitter->pointer_timestamp, jitter->packets[i].timestamp))            {               count++;            }         }         *(spx_int32_t*)ptr = count;         break;      case JITTER_BUFFER_SET_DESTROY_CALLBACK:         jitter->destroy = (void (*) (void *))ptr;         break;      case JITTER_BUFFER_GET_DESTROY_CALLBACK:         *(void (**) (void *))ptr = jitter->destroy;         break;      case JITTER_BUFFER_SET_DELAY_STEP:         jitter->delay_step = *(spx_int32_t*)ptr;         break;      case JITTER_BUFFER_GET_DELAY_STEP:         *(spx_int32_t*)ptr = jitter->delay_step;         break;      case JITTER_BUFFER_SET_CONCEALMENT_SIZE:         jitter->concealment_size = *(spx_int32_t*)ptr;         break;      case JITTER_BUFFER_GET_CONCEALMENT_SIZE:         *(spx_int32_t*)ptr = jitter->concealment_size;         break;      case JITTER_BUFFER_SET_MAX_LATE_RATE:         jitter->max_late_rate = *(spx_int32_t*)ptr;         jitter->window_size = 100*TOP_DELAY/jitter->max_late_rate;         jitter->subwindow_size = jitter->window_size/MAX_BUFFERS;         break;      case JITTER_BUFFER_GET_MAX_LATE_RATE:         *(spx_int32_t*)ptr = jitter->max_late_rate;         break;      case JITTER_BUFFER_SET_LATE_COST:         jitter->latency_tradeoff = *(spx_int32_t*)ptr;         break;      case JITTER_BUFFER_GET_LATE_COST:         *(spx_int32_t*)ptr = jitter->latency_tradeoff;         break;      default:         speex_warning_int("Unknown jitter_buffer_ctl request: ", request);         return -1;   }   return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -