mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-03-20 20:40:15 +00:00
Pbuf: use high_resolution_timer instead of timespec
This commit is contained in:
@@ -576,6 +576,7 @@ static void *audio_receiver_thread(void *arg)
|
||||
|
||||
if(s->receiver == NET_NATIVE) {
|
||||
gettimeofday(&curr_time, NULL);
|
||||
auto curr_time_hr = std::chrono::high_resolution_clock::now();
|
||||
ts = std::chrono::duration_cast<std::chrono::duration<double>>(s->start_time - std::chrono::steady_clock::now()).count() * 90000;
|
||||
rtp_update(s->audio_network_device, curr_time);
|
||||
rtp_send_ctrl(s->audio_network_device, ts, 0, curr_time);
|
||||
@@ -612,12 +613,12 @@ static void *audio_receiver_thread(void *arg)
|
||||
// We iterate in loop since there can be more than one frmae present in
|
||||
// the playout buffer and it would be discarded by following pbuf_remove()
|
||||
// call.
|
||||
while (pbuf_decode(cp->playout_buffer, curr_time, decode_audio_frame, &pbuf_data)) {
|
||||
while (pbuf_decode(cp->playout_buffer, curr_time_hr, decode_audio_frame, &pbuf_data)) {
|
||||
decoded = true;
|
||||
}
|
||||
}
|
||||
|
||||
pbuf_remove(cp->playout_buffer, curr_time);
|
||||
pbuf_remove(cp->playout_buffer, curr_time_hr);
|
||||
cp = pdb_iter_next(&it);
|
||||
|
||||
if (decoded)
|
||||
@@ -627,6 +628,7 @@ static void *audio_receiver_thread(void *arg)
|
||||
}else if(s->receiver == NET_STANDARD){
|
||||
//TODO now expecting to receive mulaw standard RTP (decode frame mulaw callback) , next steps, to be dynamic...
|
||||
gettimeofday(&curr_time, NULL);
|
||||
auto curr_time_hr = std::chrono::high_resolution_clock::now();
|
||||
ts = std::chrono::duration_cast<std::chrono::duration<double>>(s->start_time - std::chrono::steady_clock::now()).count() * 90000;
|
||||
rtp_update(s->audio_network_device, curr_time);
|
||||
rtp_send_ctrl(s->audio_network_device, ts, 0, curr_time);
|
||||
@@ -639,7 +641,7 @@ static void *audio_receiver_thread(void *arg)
|
||||
|
||||
while (cp != NULL) {
|
||||
// should be perhaps run iteratively? similarly to NET_NATIVE
|
||||
if (pbuf_decode(cp->playout_buffer, curr_time, decode_audio_frame_mulaw, &pbuf_data)) {
|
||||
if (pbuf_decode(cp->playout_buffer, curr_time_hr, decode_audio_frame_mulaw, &pbuf_data)) {
|
||||
bool failed = false;
|
||||
if(s->echo_state) {
|
||||
#ifdef HAVE_SPEEX
|
||||
@@ -672,7 +674,7 @@ echo_play(s->echo_state, &pbuf_data.buffer);
|
||||
audio_playback_put_frame(s->audio_playback_device, &pbuf_data.buffer);
|
||||
}
|
||||
|
||||
pbuf_remove(cp->playout_buffer, curr_time);
|
||||
pbuf_remove(cp->playout_buffer, curr_time_hr);
|
||||
cp = pdb_iter_next(&it);
|
||||
}
|
||||
pdb_iter_done(&it);
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
#include "config_win32.h"
|
||||
#include "debug.h"
|
||||
#include "perf.h"
|
||||
#include "tv.h"
|
||||
#include "rtp/rtp.h"
|
||||
#include "rtp/rtp_callback.h"
|
||||
#include "rtp/ptime.h"
|
||||
@@ -72,8 +71,8 @@ struct pbuf_node {
|
||||
struct pbuf_node *nxt;
|
||||
struct pbuf_node *prv;
|
||||
uint32_t rtp_timestamp; /* RTP timestamp for the frame */
|
||||
struct timeval arrival_time; /* Arrival time of first packet in frame */
|
||||
struct timeval playout_time; /* Playout time for the frame */
|
||||
std::chrono::high_resolution_clock::time_point arrival_time; /* Arrival time of first packet in frame */
|
||||
std::chrono::high_resolution_clock::time_point playout_time; /* Playout time for the frame */
|
||||
struct coded_data *cdata; /* */
|
||||
int decoded; /* Non-zero if we've decoded this frame */
|
||||
int mbit; /* determines if mbit of frame had been seen */
|
||||
@@ -84,7 +83,7 @@ struct pbuf_node {
|
||||
struct pbuf {
|
||||
struct pbuf_node *frst;
|
||||
struct pbuf_node *last;
|
||||
double playout_delay;
|
||||
long long int playout_delay_us;
|
||||
|
||||
// for statistics
|
||||
/// @todo figure out packet duplication
|
||||
@@ -159,14 +158,14 @@ struct pbuf *pbuf_init(int delay_ms)
|
||||
{
|
||||
struct pbuf *playout_buf = NULL;
|
||||
|
||||
playout_buf = calloc(1, sizeof(struct pbuf));
|
||||
playout_buf = (struct pbuf *) calloc(1, sizeof(struct pbuf));
|
||||
if (playout_buf != NULL) {
|
||||
playout_buf->frst = NULL;
|
||||
playout_buf->last = NULL;
|
||||
/* Playout delay... should really be adaptive, based on the */
|
||||
/* jitter, but we use a (conservative) fixed 32ms delay for */
|
||||
/* now (2 video frames at 60fps). */
|
||||
playout_buf->playout_delay = 0.032 + delay_ms / 1000.0;
|
||||
playout_buf->playout_delay_us = 0.032 * 1000 * 1000 + delay_ms * 1000.0;
|
||||
playout_buf->last_rtp_seq = -1;
|
||||
} else {
|
||||
debug_msg("Failed to allocate memory for playout buffer\n");
|
||||
@@ -188,7 +187,7 @@ static void add_coded_unit(struct pbuf_node *node, rtp_packet * pkt)
|
||||
assert(node->rtp_timestamp == pkt->ts);
|
||||
assert(node->cdata != NULL);
|
||||
|
||||
tmp = malloc(sizeof(struct coded_data));
|
||||
tmp = (struct coded_data *) malloc(sizeof(struct coded_data));
|
||||
if (tmp == NULL) {
|
||||
/* this is bad, out of memory, drop the packet... */
|
||||
free(pkt);
|
||||
@@ -232,26 +231,22 @@ static void add_coded_unit(struct pbuf_node *node, rtp_packet * pkt)
|
||||
}
|
||||
}
|
||||
|
||||
static struct pbuf_node *create_new_pnode(rtp_packet * pkt, double playout_delay)
|
||||
static struct pbuf_node *create_new_pnode(rtp_packet * pkt, long long playout_delay_us)
|
||||
{
|
||||
struct pbuf_node *tmp;
|
||||
|
||||
perf_record(UVP_CREATEPBUF, pkt->ts);
|
||||
|
||||
tmp = malloc(sizeof(struct pbuf_node));
|
||||
tmp = new struct pbuf_node();
|
||||
if (tmp != NULL) {
|
||||
tmp->magic = PBUF_MAGIC;
|
||||
tmp->completed = false;
|
||||
tmp->nxt = NULL;
|
||||
tmp->prv = NULL;
|
||||
tmp->decoded = 0;
|
||||
tmp->rtp_timestamp = pkt->ts;
|
||||
tmp->mbit = pkt->m;
|
||||
gettimeofday(&(tmp->arrival_time), NULL);
|
||||
gettimeofday(&(tmp->playout_time), NULL);
|
||||
tv_add(&(tmp->playout_time), playout_delay);
|
||||
tmp->playout_time =
|
||||
tmp->arrival_time = std::chrono::high_resolution_clock::now();
|
||||
tmp->playout_time += std::chrono::microseconds(playout_delay_us);
|
||||
|
||||
tmp->cdata = malloc(sizeof(struct coded_data));
|
||||
tmp->cdata = (struct coded_data *) malloc(sizeof(struct coded_data));
|
||||
if (tmp->cdata != NULL) {
|
||||
tmp->cdata->nxt = NULL;
|
||||
tmp->cdata->prv = NULL;
|
||||
@@ -259,7 +254,7 @@ static struct pbuf_node *create_new_pnode(rtp_packet * pkt, double playout_delay
|
||||
tmp->cdata->data = pkt;
|
||||
} else {
|
||||
free(pkt);
|
||||
free(tmp);
|
||||
delete tmp;
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
@@ -319,7 +314,7 @@ void pbuf_insert(struct pbuf *playout_buf, rtp_packet * pkt)
|
||||
|
||||
if (playout_buf->frst == NULL && playout_buf->last == NULL) {
|
||||
/* playout buffer is empty - add new frame */
|
||||
playout_buf->frst = create_new_pnode(pkt, playout_buf->playout_delay);
|
||||
playout_buf->frst = create_new_pnode(pkt, playout_buf->playout_delay_us);
|
||||
playout_buf->last = playout_buf->frst;
|
||||
return;
|
||||
}
|
||||
@@ -331,7 +326,7 @@ void pbuf_insert(struct pbuf *playout_buf, rtp_packet * pkt)
|
||||
} else {
|
||||
if (playout_buf->last->rtp_timestamp < pkt->ts) {
|
||||
/* Packet belongs to a new frame... */
|
||||
tmp = create_new_pnode(pkt, playout_buf->playout_delay);
|
||||
tmp = create_new_pnode(pkt, playout_buf->playout_delay_us);
|
||||
playout_buf->last->nxt = tmp;
|
||||
playout_buf->last->completed = true;
|
||||
tmp->prv = playout_buf->last;
|
||||
@@ -381,7 +376,7 @@ static void free_cdata(struct coded_data *head)
|
||||
}
|
||||
}
|
||||
|
||||
void pbuf_remove(struct pbuf *playout_buf, struct timeval curr_time)
|
||||
void pbuf_remove(struct pbuf *playout_buf, std::chrono::high_resolution_clock::time_point const & curr_time)
|
||||
{
|
||||
/* Remove previously decoded frames that have passed their playout */
|
||||
/* time from the playout buffer. Incomplete frames that have passed */
|
||||
@@ -394,7 +389,7 @@ void pbuf_remove(struct pbuf *playout_buf, struct timeval curr_time)
|
||||
curr = playout_buf->frst;
|
||||
while (curr != NULL) {
|
||||
temp = curr->nxt;
|
||||
if (tv_gt(curr_time, curr->playout_time) && frame_complete(curr)) {
|
||||
if (curr_time > curr->playout_time && frame_complete(curr)) {
|
||||
if (curr == playout_buf->frst) {
|
||||
playout_buf->frst = curr->nxt;
|
||||
}
|
||||
@@ -408,7 +403,7 @@ void pbuf_remove(struct pbuf *playout_buf, struct timeval curr_time)
|
||||
curr->prv->nxt = curr->nxt;
|
||||
}
|
||||
free_cdata(curr->cdata);
|
||||
free(curr);
|
||||
delete curr;
|
||||
} else {
|
||||
/* The playout buffer is stored in order, so once */
|
||||
/* we see one packet that has not yet reached it's */
|
||||
@@ -445,7 +440,7 @@ int pbuf_is_empty(struct pbuf *playout_buf)
|
||||
}
|
||||
|
||||
int
|
||||
pbuf_decode(struct pbuf *playout_buf, struct timeval curr_time,
|
||||
pbuf_decode(struct pbuf *playout_buf, std::chrono::high_resolution_clock::time_point const & curr_time,
|
||||
decode_frame_t decode_func, void *data)
|
||||
{
|
||||
/* Find the first complete frame that has reached it's playout */
|
||||
@@ -458,7 +453,7 @@ pbuf_decode(struct pbuf *playout_buf, struct timeval curr_time,
|
||||
curr = playout_buf->frst;
|
||||
while (curr != NULL) {
|
||||
if (!curr->decoded
|
||||
&& tv_gt(curr_time, curr->playout_time)
|
||||
&& curr_time > curr->playout_time
|
||||
) {
|
||||
if (frame_complete(curr)) {
|
||||
struct pbuf_stats stats = { playout_buf->received_pkts_cum,
|
||||
@@ -479,6 +474,6 @@ pbuf_decode(struct pbuf *playout_buf, struct timeval curr_time,
|
||||
|
||||
void pbuf_set_playout_delay(struct pbuf *playout_buf, double playout_delay)
|
||||
{
|
||||
playout_buf->playout_delay = playout_delay;
|
||||
playout_buf->playout_delay_us = playout_delay * 1000 * 1000;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,6 @@
|
||||
|
||||
#include "audio/audio.h"
|
||||
#include "rtp/rtp.h"
|
||||
#include "utils/list.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -111,19 +110,29 @@ struct pbuf_audio_data {
|
||||
* @param decode_data
|
||||
*/
|
||||
typedef int decode_frame_t(struct coded_data *cdata, void *decode_data, struct pbuf_stats *stats);
|
||||
|
||||
/*
|
||||
* External interface:
|
||||
* External C interface:
|
||||
*/
|
||||
struct pbuf *pbuf_init(int delay_ms);
|
||||
void pbuf_insert(struct pbuf *playout_buf, rtp_packet *r);
|
||||
int pbuf_is_empty(struct pbuf *playout_buf);
|
||||
int pbuf_decode(struct pbuf *playout_buf, struct timeval curr_time,
|
||||
decode_frame_t decode_func, void *data);
|
||||
//struct video_frame *framebuffer, int i, struct state_decoder *decoder);
|
||||
void pbuf_remove(struct pbuf *playout_buf, struct timeval curr_time);
|
||||
void pbuf_set_playout_delay(struct pbuf *playout_buf, double playout_delay);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <chrono>
|
||||
|
||||
/*
|
||||
* External C++ interface:
|
||||
*/
|
||||
int pbuf_is_empty(struct pbuf *playout_buf);
|
||||
int pbuf_decode(struct pbuf *playout_buf, std::chrono::high_resolution_clock::time_point const & curr_time,
|
||||
decode_frame_t decode_func, void *data);
|
||||
//struct video_frame *framebuffer, int i, struct state_decoder *decoder);
|
||||
void pbuf_remove(struct pbuf *playout_buf, std::chrono::high_resolution_clock::time_point const & curr_time);
|
||||
void pbuf_set_playout_delay(struct pbuf *playout_buf, double playout_delay);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -322,6 +322,7 @@ void *ultragrid_rtp_video_rxtx::receiver_loop()
|
||||
struct timeval timeout;
|
||||
/* Housekeeping and RTCP... */
|
||||
gettimeofday(&curr_time, NULL);
|
||||
auto curr_time_hr = std::chrono::high_resolution_clock::now();
|
||||
ts = std::chrono::duration_cast<std::chrono::duration<double>>(m_start_time - std::chrono::steady_clock::now()).count() * 90000;
|
||||
|
||||
rtp_update(m_network_devices[0], curr_time);
|
||||
@@ -392,7 +393,7 @@ void *ultragrid_rtp_video_rxtx::receiver_loop()
|
||||
|
||||
/* Decode and render video... */
|
||||
if (pbuf_decode
|
||||
(cp->playout_buffer, curr_time, decode_video_frame, vdecoder_state)) {
|
||||
(cp->playout_buffer, curr_time_hr, decode_video_frame, vdecoder_state)) {
|
||||
tiles_post++;
|
||||
/* we have data from all connections we need */
|
||||
if(tiles_post == m_connections_count)
|
||||
@@ -441,7 +442,7 @@ void *ultragrid_rtp_video_rxtx::receiver_loop()
|
||||
}
|
||||
}
|
||||
|
||||
pbuf_remove(cp->playout_buffer, curr_time);
|
||||
pbuf_remove(cp->playout_buffer, curr_time_hr);
|
||||
cp = pdb_iter_next(&it);
|
||||
}
|
||||
pdb_iter_done(&it);
|
||||
|
||||
Reference in New Issue
Block a user