UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
pbuf.h File Reference
#include "audio/types.h"
#include "rtp/rtp.h"
#include "tv.h"
Include dependency graph for pbuf.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  coded_data
 
struct  pbuf_audio_data
 
struct  pbuf_stats
 
struct  vcodec_state
 

Typedefs

typedef int decode_frame_t(struct coded_data *cdata, void *decode_data, struct pbuf_stats *stats)
 

Functions

int pbuf_decode (struct pbuf *playout_buf, time_ns_t curr_time, decode_frame_t decode_func, void *data)
 
void pbuf_destroy (struct pbuf *)
 
struct pbuf * pbuf_init (volatile int *delay_ms)
 
void pbuf_insert (struct pbuf *playout_buf, rtp_packet *r)
 
int pbuf_is_empty (struct pbuf *playout_buf)
 
void pbuf_remove (struct pbuf *playout_buf, time_ns_t curr_time)
 
void pbuf_set_playout_delay (struct pbuf *playout_buf, double playout_delay)
 

Typedef Documentation

◆ decode_frame_t

typedef int decode_frame_t(struct coded_data *cdata, void *decode_data, struct pbuf_stats *stats)
Parameters
decode_data

Definition at line 110 of file pbuf.h.

Function Documentation

◆ pbuf_decode()

int pbuf_decode ( struct pbuf * playout_buf,
time_ns_t curr_time,
decode_frame_t decode_func,
void * data )

Definition at line 562 of file pbuf.c.

564{
565 /* Find the first complete frame that has reached it's playout */
566 /* time, and decode it into the framebuffer. Mark the frame as */
567 /* decoded, but otherwise leave it in the playout buffer. */
568 struct pbuf_node *curr;
569
570 pbuf_validate(playout_buf);
571
572 curr = playout_buf->frst;
573 while (curr != NULL) {
574 if (!curr->decoded
575 && curr_time > curr->playout_time
576 ) {
577 if (frame_complete(curr)) {
578 struct pbuf_stats stats = { playout_buf->received_pkts_cum,
579 playout_buf->expected_pkts_cum };
580 int ret = decode_func(curr->cdata, data, &stats);
581 curr->decoded = 1;
582 return ret;
583 } else {
584 if (curr_time > curr->playout_time + 1 * NS_IN_SEC) {
585 curr->completed = true;
586 }
588 ("Unable to decode frame due to missing data (RTP TS=%u)\n",
589 curr->rtp_timestamp);
590 }
591 }
592 curr = curr->nxt;
593 }
594 return 0;
595}
#define debug_msg(...)
#define debug_msg(...) log_msg(LOG_LEVEL_DEBUG, "[pid/%d +%d %s] ", getpid(), LINE,...
Definition debug.h:92
static void pbuf_validate(struct pbuf *playout_buf)
Definition pbuf.c:121
static int frame_complete(struct pbuf_node *frame)
Definition pbuf.c:540
int decoded
Definition pbuf.c:90
uint32_t rtp_timestamp
Definition pbuf.c:85
struct pbuf_node * nxt
Definition pbuf.c:83
time_ns_t playout_time
Definition pbuf.c:87
struct coded_data * cdata
Definition pbuf.c:89
bool completed
Definition pbuf.c:93
struct pbuf_node * frst
Definition pbuf.c:97
long long int expected_pkts_cum
Definition pbuf.c:108
long long int received_pkts_cum
Definition pbuf.c:108
#define NS_IN_SEC
Definition tv.h:92

References pbuf_node::cdata, pbuf_node::completed, debug_msg, pbuf_node::decoded, pbuf::expected_pkts_cum, frame_complete(), pbuf::frst, NS_IN_SEC, pbuf_node::nxt, pbuf_validate(), pbuf_node::playout_time, pbuf::received_pkts_cum, and pbuf_node::rtp_timestamp.

Referenced by audio_receiver_thread(), ultragrid_rtp_video_rxtx::receiver_loop(), and vidcap_rtsp_thread().

Here is the call graph for this function:

◆ pbuf_destroy()

void pbuf_destroy ( struct pbuf * playout_buf)

Definition at line 195 of file pbuf.c.

195 {
196 if (playout_buf) {
197 pbuf_validate(playout_buf);
198
199 if (playout_buf->received_pkts_cum) { // print only if relevant
200 log_msg(LOG_LEVEL_INFO, "Pbuf: total %lld/%lld packets received "
201 "(%.5lf%%).\n",
202 playout_buf->received_pkts_cum,
203 playout_buf->expected_pkts_cum,
204 (double) playout_buf->received_pkts_cum /
205 playout_buf->expected_pkts_cum * 100.0);
206 }
207
208 struct pbuf_node *curr = playout_buf->frst;
209 while (curr != NULL) {
210 struct pbuf_node *temp = curr->nxt;
211 if (curr == playout_buf->frst) {
212 playout_buf->frst = curr->nxt;
213 }
214 if (curr == playout_buf->last) {
215 playout_buf->last = curr->prv;
216 }
217 if (curr->nxt != NULL) {
218 curr->nxt->prv = curr->prv;
219 }
220 if (curr->prv != NULL) {
221 curr->prv->nxt = curr->nxt;
222 }
223 free_cdata(curr->cdata);
224 free(curr);
225 curr = temp;
226 }
227 free(playout_buf);
228 }
229}
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
static void free_cdata(struct coded_data *head)
Definition pbuf.c:486
struct pbuf_node * prv
Definition pbuf.c:84
struct pbuf_node * last
Definition pbuf.c:98

References pbuf_node::cdata, pbuf::expected_pkts_cum, free_cdata(), pbuf::frst, pbuf::last, LOG_LEVEL_INFO, log_msg(), pbuf_node::nxt, pbuf_validate(), pbuf_node::prv, and pbuf::received_pkts_cum.

Referenced by pdb_destroy_item().

Here is the call graph for this function:

◆ pbuf_init()

struct pbuf * pbuf_init ( volatile int * delay_ms)

Definition at line 174 of file pbuf.c.

175{
176 struct pbuf *playout_buf = NULL;
177
178 playout_buf = (struct pbuf *) calloc(1, sizeof(struct pbuf));
179 if (playout_buf != NULL) {
180 playout_buf->frst = NULL;
181 playout_buf->last = NULL;
182 /* Playout delay... should really be adaptive, based on the */
183 /* jitter, but we use a (conservative) fixed 32ms delay for */
184 /* now (2 video frames at 60fps). */
185 playout_buf->offset_ms = delay_ms;
186 playout_buf->playout_delay_us = 0.032 * 1000 * 1000;
187 playout_buf->last_report_seq = -1;
189 } else {
190 debug_msg("Failed to allocate memory for playout buffer\n");
191 }
192 return playout_buf;
193}
@ DEFAULT_STATS_INTERVAL
Definition pbuf.c:74
Definition pbuf.c:96
int stats_interval
Definition pbuf.c:103
int last_report_seq
Definition pbuf.c:105
long long int playout_delay_us
Definition pbuf.c:99
volatile int * offset_ms
Definition pbuf.c:100

References debug_msg, DEFAULT_STATS_INTERVAL, pbuf::frst, pbuf::last, pbuf::last_report_seq, pbuf::offset_ms, pbuf::playout_delay_us, and pbuf::stats_interval.

Referenced by pdb_create_item().

◆ pbuf_insert()

void pbuf_insert ( struct pbuf * playout_buf,
rtp_packet * r )

Definition at line 420 of file pbuf.c.

421{
422 struct pbuf_node *tmp;
423
424 pbuf_validate(playout_buf);
425 pbuf_process_stats(playout_buf, pkt);
426
427 if (playout_buf->frst == NULL && playout_buf->last == NULL) {
428 /* playout buffer is empty - add new frame */
429 playout_buf->frst = create_new_pnode(pkt, playout_buf->playout_delay_us + 1000 * (playout_buf->offset_ms ? *playout_buf->offset_ms : 0));
430 playout_buf->last = playout_buf->frst;
431 return;
432 }
433
434 if (playout_buf->last->rtp_timestamp == pkt->ts) {
435 if (playout_buf->last->decoded) {
436 log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Late data for already decoded frame!\n");
437 }
438 /* Packet belongs to last frame in playout_buf this is the */
439 /* most likely scenario - although... */
440 add_coded_unit(playout_buf->last, pkt);
441 } else {
442 if (playout_buf->last->rtp_timestamp < pkt->ts ||
443 playout_buf->last->rtp_timestamp - pkt->ts >
444 UINT32_MAX - WRAPAROUND_THRESHOLD) {
445 /* Packet belongs to a new frame... */
446 tmp = create_new_pnode(pkt, playout_buf->playout_delay_us + 1000 * (playout_buf->offset_ms ? *playout_buf->offset_ms : 0));
447 playout_buf->last->nxt = tmp;
448 playout_buf->last->completed = true;
449 tmp->prv = playout_buf->last;
450 playout_buf->last = tmp;
451 } else {
452 bool discard_pkt = false;
453 /* Packet belongs to a previous frame... */
454 if (playout_buf->frst->rtp_timestamp > pkt->ts ||
455 pkt->ts - playout_buf->frst->rtp_timestamp >
456 UINT32_MAX - WRAPAROUND_THRESHOLD) {
457 debug_msg("A very old packet - discarded\n");
458 discard_pkt = true;
459 } else {
461 ("A packet for a previous frame, but might still be useful\n");
462 struct pbuf_node *curr = playout_buf->last;
463 while(curr != playout_buf->frst && curr->rtp_timestamp > pkt->ts){
464 curr = curr->prv;
465 }
466 if (curr->rtp_timestamp == pkt->ts) {
467 /* Packet belongs to a previous existing frame... */
468 add_coded_unit(curr, pkt);
469 } else {
470 /* Packet belongs to a frame that is not present */
471 discard_pkt = true;
472 }
473 }
474 if (discard_pkt) {
475 if (pkt->m) {
477 ("Oops... dropped packet with M bit set\n");
478 }
479 free(pkt);
480 }
481 }
482 }
483 pbuf_validate(playout_buf);
484}
#define LOG_LEVEL_VERBOSE
Definition debug.h:63
static struct pbuf_node * create_new_pnode(rtp_packet *pkt, long long playout_delay_us)
Definition pbuf.c:280
static void add_coded_unit(struct pbuf_node *node, rtp_packet *pkt)
Definition pbuf.c:236
@ WRAPAROUND_THRESHOLD
Definition pbuf.c:76
#define MOD_NAME
Definition pbuf.c:80
static void pbuf_process_stats(struct pbuf *playout_buf, rtp_packet *pkt)
Definition pbuf.c:345

References add_coded_unit(), pbuf_node::completed, create_new_pnode(), debug_msg, pbuf_node::decoded, pbuf::frst, pbuf::last, LOG_LEVEL_VERBOSE, log_msg(), MOD_NAME, pbuf_node::nxt, pbuf::offset_ms, pbuf_process_stats(), pbuf_validate(), pbuf::playout_delay_us, pbuf_node::prv, pbuf_node::rtp_timestamp, and WRAPAROUND_THRESHOLD.

Referenced by rtp_recv_callback().

Here is the call graph for this function:

◆ pbuf_is_empty()

int pbuf_is_empty ( struct pbuf * playout_buf)

Definition at line 553 of file pbuf.c.

554{
555 if (playout_buf->frst == NULL)
556 return TRUE;
557 else
558 return FALSE;
559}
#define TRUE
#define FALSE

References FALSE, pbuf::frst, and TRUE.

Referenced by audio_receiver_thread(), and ultragrid_rtp_video_rxtx::receiver_loop().

◆ pbuf_remove()

void pbuf_remove ( struct pbuf * playout_buf,
time_ns_t curr_time )

Definition at line 498 of file pbuf.c.

499{
500 /* Remove previously decoded frames that have passed their playout */
501 /* time from the playout buffer. Incomplete frames that have passed */
502 /* their playout time are also discarded. */
503
504 struct pbuf_node *curr, *temp;
505
506 pbuf_validate(playout_buf);
507
508 curr = playout_buf->frst;
509 while (curr != NULL) {
510 temp = curr->nxt;
511 if (curr_time > curr->deletion_time && frame_complete(curr)) {
512 if (curr == playout_buf->frst) {
513 playout_buf->frst = curr->nxt;
514 }
515 if (curr == playout_buf->last) {
516 playout_buf->last = curr->prv;
517 }
518 if (curr->nxt != NULL) {
519 curr->nxt->prv = curr->prv;
520 }
521 if (curr->prv != NULL) {
522 curr->prv->nxt = curr->nxt;
523 }
524 free_cdata(curr->cdata);
525 free(curr);
526 } else {
527 /* The playout buffer is stored in order, so once */
528 /* we see one packet that has not yet reached it's */
529 /* playout time, we can be sure none of the others */
530 /* will have done so... */
531 break;
532 }
533 curr = temp;
534 }
535
536 pbuf_validate(playout_buf);
537 return;
538}
time_ns_t deletion_time
Definition pbuf.c:88

References pbuf_node::cdata, pbuf_node::deletion_time, frame_complete(), free_cdata(), pbuf::frst, pbuf::last, pbuf_node::nxt, pbuf_validate(), and pbuf_node::prv.

Referenced by audio_receiver_thread(), ultragrid_rtp_video_rxtx::receiver_loop(), and vidcap_rtsp_thread().

Here is the call graph for this function:

◆ pbuf_set_playout_delay()

void pbuf_set_playout_delay ( struct pbuf * playout_buf,
double playout_delay )

Definition at line 597 of file pbuf.c.

598{
599 playout_buf->playout_delay_us = playout_delay * 1000 * 1000;
600}

References pbuf::playout_delay_us.

Referenced by audio_receiver_thread(), and ultragrid_rtp_video_rxtx::receiver_process_messages().