Pbuf: deletion delay only for inter-frame compress

This commit is contained in:
Martin Pulec
2013-05-15 12:33:54 +02:00
parent a1a5a3f8a8
commit 42ec499b67
10 changed files with 180 additions and 33 deletions

View File

@@ -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 \

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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
View 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
View 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_

View File

@@ -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;

View File

@@ -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);