mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-03-21 15:40:21 +00:00
Pbuf: deletion delay only for inter-frame compress
This commit is contained in:
@@ -89,6 +89,7 @@ OBJS = @OBJS@ \
|
||||
src/crypto/random.o \
|
||||
src/ihdtv/ihdtv.o \
|
||||
src/utils/fs_lock.o \
|
||||
src/utils/list.o \
|
||||
src/utils/packet_counter.o \
|
||||
src/utils/resource_manager.o \
|
||||
src/utils/ring_buffer.o \
|
||||
|
||||
@@ -130,6 +130,7 @@ void destroy_decoder(struct vcodec_state *video_decoder_state) {
|
||||
return;
|
||||
}
|
||||
|
||||
simple_linked_list_destroy(video_decoder_state->messages);
|
||||
decoder_destroy_extrn(video_decoder_state->decoder);
|
||||
|
||||
free(video_decoder_state);
|
||||
|
||||
16
src/main.c
16
src/main.c
@@ -492,6 +492,7 @@ static struct vcodec_state *new_decoder(struct state_uv *uv) {
|
||||
struct vcodec_state *state = calloc(1, sizeof(struct vcodec_state));
|
||||
|
||||
if(state) {
|
||||
state->messages = simple_linked_list_init();
|
||||
state->decoder = decoder_init(uv->decoder_mode, uv->postprocess, uv->display_device);
|
||||
|
||||
if(!state->decoder) {
|
||||
@@ -653,10 +654,19 @@ static void *receiver_thread(void *arg)
|
||||
last_buf_size = new_size;
|
||||
}
|
||||
|
||||
if(cp->video_decoder_state->set_fps) {
|
||||
while(simple_linked_list_size(cp->video_decoder_state->messages) > 0) {
|
||||
struct vcodec_message *msg =
|
||||
simple_linked_list_pop(cp->video_decoder_state->messages);
|
||||
|
||||
assert(msg->type == FPS_CHANGED);
|
||||
struct fps_changed_message *data = msg->data;
|
||||
|
||||
pbuf_set_playout_delay(cp->playout_buffer,
|
||||
1.0 / cp->video_decoder_state->set_fps);
|
||||
cp->video_decoder_state->set_fps = 0.0;
|
||||
1.0 / data->val,
|
||||
1.0 / data->val * (data->interframe_codec ? 2 : 1)
|
||||
);
|
||||
free(data);
|
||||
free(msg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -168,6 +168,7 @@ struct state_decoder {
|
||||
unsigned long int corrupted;
|
||||
|
||||
double set_fps; // "message" passed to our master
|
||||
codec_t codec;
|
||||
bool slow;
|
||||
};
|
||||
|
||||
@@ -1271,6 +1272,7 @@ static int check_for_mode_change(struct state_decoder *decoder, uint32_t *hdr, s
|
||||
decoder->frame = *frame;
|
||||
ret = TRUE;
|
||||
decoder->set_fps = fps;
|
||||
decoder->codec = color_spec;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1320,8 +1322,14 @@ int decode_frame(struct coded_data *cdata, void *decode_data)
|
||||
|
||||
// first, dispatch "messages"
|
||||
if(decoder->set_fps) {
|
||||
pbuf_data->set_fps = decoder->set_fps;
|
||||
decoder->set_fps = 0.0;
|
||||
struct vcodec_message *msg = malloc(sizeof(struct vcodec_message));
|
||||
struct fps_changed_message *data = malloc(sizeof(struct fps_changed_message));
|
||||
msg->type = FPS_CHANGED;
|
||||
msg->data = data;
|
||||
data->val = decoder->set_fps;
|
||||
data->interframe_codec = is_codec_interframe(decoder->codec);
|
||||
simple_linked_list_append(pbuf_data->messages, msg);
|
||||
decoder->set_fps = 0;
|
||||
}
|
||||
|
||||
int pt;
|
||||
|
||||
@@ -89,6 +89,7 @@ struct pbuf {
|
||||
struct pbuf_node *frst;
|
||||
struct pbuf_node *last;
|
||||
double playout_delay;
|
||||
double deletion_delay;
|
||||
};
|
||||
|
||||
/*********************************************************************************/
|
||||
@@ -157,7 +158,8 @@ struct pbuf *pbuf_init(void)
|
||||
/* 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;
|
||||
playout_buf->deletion_delay =
|
||||
playout_buf->playout_delay = 0.032;
|
||||
} else {
|
||||
debug_msg("Failed to allocate memory for playout buffer\n");
|
||||
}
|
||||
@@ -193,7 +195,8 @@ 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, double playout_delay,
|
||||
double deletion_delay)
|
||||
{
|
||||
struct pbuf_node *tmp;
|
||||
|
||||
@@ -211,7 +214,7 @@ static struct pbuf_node *create_new_pnode(rtp_packet * pkt, double playout_delay
|
||||
gettimeofday(&(tmp->playout_time), NULL);
|
||||
tmp->deletion_time = tmp->playout_time;
|
||||
tv_add(&(tmp->playout_time), playout_delay);
|
||||
tv_add(&(tmp->deletion_time), playout_delay * 2);
|
||||
tv_add(&(tmp->deletion_time), deletion_delay);
|
||||
|
||||
tmp->cdata = malloc(sizeof(struct coded_data));
|
||||
if (tmp->cdata != NULL) {
|
||||
@@ -238,7 +241,8 @@ 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,
|
||||
playout_buf->deletion_delay);
|
||||
playout_buf->last = playout_buf->frst;
|
||||
return;
|
||||
}
|
||||
@@ -250,7 +254,8 @@ 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,
|
||||
playout_buf->deletion_delay);
|
||||
playout_buf->last->nxt = tmp;
|
||||
tmp->prv = playout_buf->last;
|
||||
playout_buf->last = tmp;
|
||||
@@ -407,7 +412,9 @@ audio_pbuf_decode(struct pbuf *playout_buf, struct timeval curr_time,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pbuf_set_playout_delay(struct pbuf *playout_buf, double playout_delay)
|
||||
void pbuf_set_playout_delay(struct pbuf *playout_buf, double playout_delay, double deletion_delay)
|
||||
{
|
||||
playout_buf->playout_delay = playout_delay;
|
||||
playout_buf->deletion_delay = deletion_delay;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
#include "video_display.h"
|
||||
|
||||
#include "audio/audio.h"
|
||||
#include "utils/list.h"
|
||||
|
||||
/* The coded representation of a single frame */
|
||||
struct coded_data {
|
||||
@@ -82,13 +83,23 @@ struct pbuf;
|
||||
struct state_decoder;
|
||||
struct state_audio_decoder;
|
||||
|
||||
struct vcodec_message {
|
||||
enum { FPS_CHANGED } type;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct fps_changed_message {
|
||||
double val;
|
||||
unsigned interframe_codec:1;
|
||||
};
|
||||
|
||||
struct vcodec_state {
|
||||
struct display *display;
|
||||
struct state_decoder *decoder;
|
||||
unsigned int max_frame_size; // maximal frame size
|
||||
// to be returned to caller by a decoder to allow him adjust buffers accordingly
|
||||
unsigned int decoded;
|
||||
double set_fps;
|
||||
struct simple_linked_list *messages;
|
||||
};
|
||||
|
||||
struct pbuf_audio_data {
|
||||
@@ -113,6 +124,7 @@ 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);
|
||||
void pbuf_set_playout_delay(struct pbuf *playout_buf, double playout_delay,
|
||||
double deletion_delay);
|
||||
|
||||
|
||||
|
||||
74
src/utils/list.c
Normal file
74
src/utils/list.c
Normal file
@@ -0,0 +1,74 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config_unix.h"
|
||||
#include "config_win32.h"
|
||||
#endif
|
||||
|
||||
#include "utils/list.h"
|
||||
|
||||
struct node;
|
||||
|
||||
struct node {
|
||||
void *val;
|
||||
struct node *next;
|
||||
};
|
||||
|
||||
struct simple_linked_list {
|
||||
struct node *head;
|
||||
struct node *tail;
|
||||
int size;
|
||||
};
|
||||
|
||||
struct simple_linked_list *simple_linked_list_init(void)
|
||||
{
|
||||
return calloc(1, sizeof(struct simple_linked_list));
|
||||
}
|
||||
|
||||
void simple_linked_list_destroy(struct simple_linked_list *l)
|
||||
{
|
||||
struct node *n = l->head;
|
||||
while(n != NULL) {
|
||||
struct node *tmp = n;
|
||||
n = n->next;
|
||||
free(tmp);
|
||||
}
|
||||
free(l);
|
||||
}
|
||||
|
||||
void simple_linked_list_append(struct simple_linked_list *l, void *data)
|
||||
{
|
||||
struct node *new_node = calloc(1, sizeof(struct node));
|
||||
new_node->val = data;
|
||||
if(l->tail) {
|
||||
l->tail->next = new_node;
|
||||
l->tail = l->tail->next;
|
||||
} else {
|
||||
l->head = l->tail = new_node;
|
||||
}
|
||||
l->size += 1;
|
||||
}
|
||||
|
||||
void *simple_linked_list_pop(struct simple_linked_list *l)
|
||||
{
|
||||
assert(l->head != NULL);
|
||||
|
||||
struct node *n = l->head;
|
||||
void *ret;
|
||||
l->head = l->head->next;
|
||||
|
||||
if(!l->head)
|
||||
l->tail = NULL;
|
||||
|
||||
l->size--;
|
||||
|
||||
ret = n->val;
|
||||
free(n);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int simple_linked_list_size(struct simple_linked_list *l)
|
||||
{
|
||||
return l->size;
|
||||
}
|
||||
|
||||
20
src/utils/list.h
Normal file
20
src/utils/list.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef SIMPLE_LINKED_LIST_H_
|
||||
#define SIMPLE_LINKED_LIST_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct simple_linked_list;
|
||||
struct simple_linked_list *simple_linked_list_init(void);
|
||||
void simple_linked_list_destroy(struct simple_linked_list *);
|
||||
void simple_linked_list_append(struct simple_linked_list *, void *data);
|
||||
void *simple_linked_list_pop(struct simple_linked_list *);
|
||||
int simple_linked_list_size(struct simple_linked_list *);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif// SIMPLE_LINKED_LIST_H_
|
||||
@@ -66,26 +66,26 @@ static void vc_copylineToUYVY(unsigned char *dst, const unsigned char *src, int
|
||||
int rshift, int gshift, int bshift, int pix_size);
|
||||
|
||||
const struct codec_info_t codec_info[] = {
|
||||
[RGBA] = {RGBA, "RGBA", to_fourcc('R','G','B','A'), 1, 4.0, TRUE, FALSE, "rgba"},
|
||||
[UYVY] = {UYVY, "UYVY", to_fourcc('2','v','u','y'), 1, 2, FALSE, FALSE, "yuv"},
|
||||
[YUYV] = {YUYV, "YUYV", to_fourcc('Y','U','Y','V'), 1, 2, FALSE, FALSE, "yuv"},
|
||||
[Vuy2] = {Vuy2, "2vuy", to_fourcc('2','V','u','y'), 1, 2, FALSE, FALSE, "yuv"},
|
||||
[DVS8] = {DVS8, "DVS8", to_fourcc('d','v','s','8'), 1, 2, FALSE, FALSE, "yuv"},
|
||||
[R10k] = {R10k, "R10k", to_fourcc('R','1','0','k'), 1, 4, TRUE, FALSE, "r10k"},
|
||||
[v210] = {v210, "v210", to_fourcc('v','2','1','0'), 48, 8.0 / 3.0, FALSE, FALSE, "v210"},
|
||||
[DVS10] = {DVS10, "DVS10", to_fourcc('D','S','1','0'), 48, 8.0 / 3.0, FALSE, FALSE, "dvs10"},
|
||||
[DXT1] = {DXT1, "DXT1", to_fourcc('D','X','T','1'), 1, 0.5, TRUE, TRUE, "dxt1"},
|
||||
[DXT1_YUV] = {DXT1_YUV, "DXT1 YUV", to_fourcc('D','X','T','Y'), 1, 0.5, FALSE, TRUE, "dxt1y"}, /* packet YCbCr inside DXT1 channels */
|
||||
[DXT5] = {DXT5, "DXT5", to_fourcc('D','X','T','5'), 1, 1.0, FALSE, TRUE, "yog"},/* DXT5 YCoCg */
|
||||
[RGB] = {RGB, "RGB", to_fourcc('R','G','B','2'), 1, 3.0, TRUE, FALSE, "rgb"},
|
||||
[DPX10] = {DPX10, "DPX10", to_fourcc('D','P','1','0'), 1, 4.0, TRUE, FALSE, "dpx"},
|
||||
[JPEG] = {JPEG, "JPEG", to_fourcc('J','P','E','G'), 0, 0.0, FALSE, TRUE, "jpg"},
|
||||
[RAW] = {RAW, "raw", to_fourcc('r','a','w','s'), 0, 1.0, FALSE, TRUE, "raw"}, /* raw SDI */
|
||||
[H264] = {H264, "H.264", to_fourcc('A','V','C','1'), 0, 1.0, FALSE, TRUE, "h264"},
|
||||
[MJPG] = {MJPG, "MJPEG", to_fourcc('M','J','P','G'), 0, 1.0, FALSE, TRUE, "jpg"},
|
||||
[VP8] = {VP8, "VP8", to_fourcc('V','P','8','0'), 0, 1.0, FALSE, TRUE, "vp8"},
|
||||
[BGR] = {BGR, "BGR", to_fourcc('B','G','R','2'), 1, 3.0, TRUE, FALSE, "bgr"},
|
||||
{(codec_t) 0, NULL, 0, 0, 0.0, FALSE, FALSE, NULL}
|
||||
[RGBA] = {RGBA, "RGBA", to_fourcc('R','G','B','A'), 1, 4.0, TRUE, FALSE, FALSE, "rgba"},
|
||||
[UYVY] = {UYVY, "UYVY", to_fourcc('2','v','u','y'), 1, 2, FALSE, FALSE, FALSE, "yuv"},
|
||||
[YUYV] = {YUYV, "YUYV", to_fourcc('Y','U','Y','V'), 1, 2, FALSE, FALSE, FALSE, "yuv"},
|
||||
[Vuy2] = {Vuy2, "2vuy", to_fourcc('2','V','u','y'), 1, 2, FALSE, FALSE, FALSE, "yuv"},
|
||||
[DVS8] = {DVS8, "DVS8", to_fourcc('d','v','s','8'), 1, 2, FALSE, FALSE, FALSE, "yuv"},
|
||||
[R10k] = {R10k, "R10k", to_fourcc('R','1','0','k'), 1, 4, TRUE, FALSE, FALSE, "r10k"},
|
||||
[v210] = {v210, "v210", to_fourcc('v','2','1','0'), 48, 8.0 / 3.0, FALSE, FALSE, FALSE, "v210"},
|
||||
[DVS10] = {DVS10, "DVS10", to_fourcc('D','S','1','0'), 48, 8.0 / 3.0, FALSE, FALSE, FALSE, "dvs10"},
|
||||
[DXT1] = {DXT1, "DXT1", to_fourcc('D','X','T','1'), 1, 0.5, TRUE, TRUE, FALSE, "dxt1"},
|
||||
[DXT1_YUV] = {DXT1_YUV, "DXT1 YUV", to_fourcc('D','X','T','Y'), 1, 0.5, FALSE, TRUE, FALSE, "dxt1y"}, /* packet YCbCr inside DXT1 channels */
|
||||
[DXT5] = {DXT5, "DXT5", to_fourcc('D','X','T','5'), 1, 1.0, FALSE, TRUE, FALSE, "yog"},/* DXT5 YCoCg */
|
||||
[RGB] = {RGB, "RGB", to_fourcc('R','G','B','2'), 1, 3.0, TRUE, FALSE, FALSE, "rgb"},
|
||||
[DPX10] = {DPX10, "DPX10", to_fourcc('D','P','1','0'), 1, 4.0, TRUE, FALSE, FALSE, "dpx"},
|
||||
[JPEG] = {JPEG, "JPEG", to_fourcc('J','P','E','G'), 0, 0.0, FALSE, TRUE, FALSE, "jpg"},
|
||||
[RAW] = {RAW, "raw", to_fourcc('r','a','w','s'), 0, 1.0, FALSE, TRUE, FALSE, "raw"}, /* raw SDI */
|
||||
[H264] = {H264, "H.264", to_fourcc('A','V','C','1'), 0, 1.0, FALSE, TRUE, TRUE, "h264"},
|
||||
[MJPG] = {MJPG, "MJPEG", to_fourcc('M','J','P','G'), 0, 1.0, FALSE, TRUE, FALSE, "jpg"},
|
||||
[VP8] = {VP8, "VP8", to_fourcc('V','P','8','0'), 0, 1.0, FALSE, TRUE, TRUE, "vp8"},
|
||||
[BGR] = {BGR, "BGR", to_fourcc('B','G','R','2'), 1, 3.0, TRUE, FALSE, FALSE, "bgr"},
|
||||
{(codec_t) 0, NULL, 0, 0, 0.0, FALSE, FALSE, FALSE, NULL}
|
||||
};
|
||||
|
||||
/* take care that UYVY is alias for both 2vuy and dvs8, do not use
|
||||
@@ -247,6 +247,18 @@ int is_codec_opaque(codec_t codec)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_codec_interframe(codec_t codec)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (codec_info[i].name != NULL) {
|
||||
if (codec == codec_info[i].codec)
|
||||
return codec_info[i].interframe;
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_halign(codec_t codec)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -70,6 +70,7 @@ struct codec_info_t {
|
||||
double bpp;
|
||||
unsigned rgb:1;
|
||||
unsigned opaque:1;
|
||||
unsigned interframe:1;
|
||||
const char *file_extension;
|
||||
};
|
||||
|
||||
@@ -87,6 +88,7 @@ double get_bpp(codec_t codec);
|
||||
uint32_t get_fourcc(codec_t codec);
|
||||
const char *get_codec_name(codec_t codec);
|
||||
int is_codec_opaque(codec_t codec);
|
||||
int is_codec_interframe(codec_t codec);
|
||||
codec_t get_codec_from_fcc(uint32_t fourcc);
|
||||
const char *get_codec_file_extension(codec_t codec);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user