Commit 83e6c0dc authored by Simon Morlat's avatar Simon Morlat
Browse files

detect sequence number discontinuities between frames (not just only within frames).

clean code, optimize list iteration loops.
parent 7e4bdef1
......@@ -408,12 +408,6 @@ static int free_discarded_frame(const void *data, const void *d) {
return (fdiscarded != *discarded);
}
static int cseq_compare(const void *d1, const void *d2) {
Vp8RtpFmtPacket *p1 = (Vp8RtpFmtPacket *)d1;
Vp8RtpFmtPacket *p2 = (Vp8RtpFmtPacket *)d2;
return (p1->extended_cseq > p2->extended_cseq);
}
static MSVideoSize get_size_from_key_frame(Vp8RtpFmtFrame *frame) {
MSVideoSize vs;
Vp8RtpFmtPartition *partition = frame->partitions[0];
......@@ -497,19 +491,18 @@ static void add_packet_to_frame(Vp8RtpFmtFrame *frame, Vp8RtpFmtPacket *packet)
static void generate_frame_partitions_list(Vp8RtpFmtFrame *frame, MSList *packets_list) {
Vp8RtpFmtPacket *packet = NULL;
int nb_packets = ms_list_size(packets_list);
int i;
MSList *it;
frame->unnumbered_partitions = TRUE;
for (i = 0; i < nb_packets; i++) {
packet = (Vp8RtpFmtPacket *)ms_list_nth_data(packets_list, i);
for (it=packets_list;it!=NULL;it=it->next) {
packet = (Vp8RtpFmtPacket *)it->data;
if (packet->pd->pid != 0) {
frame->unnumbered_partitions = FALSE;
break;
}
}
for (i = 0; i < nb_packets; i++) {
packet = (Vp8RtpFmtPacket *)ms_list_nth_data(packets_list, i);
for (it=packets_list;it!=NULL;it=it->next) {
packet = (Vp8RtpFmtPacket *)it->data;
if (packet->error == Vp8RtpFmtOk) {
add_packet_to_frame(frame, packet);
} else {
......@@ -534,12 +527,19 @@ static void mark_frame_as_incomplete(Vp8RtpFmtUnpackerCtx *ctx, Vp8RtpFmtFrame *
}
}
static void check_frame_partitions_list(Vp8RtpFmtUnpackerCtx *ctx, Vp8RtpFmtFrame *frame) {
static bool_t has_sequence_inconsistency(const MSList *packets){
Vp8RtpFmtPacket *packet;
const MSList *elem;
for(elem=packets;elem!=NULL;elem=elem->next){
packet=(Vp8RtpFmtPacket*)elem->data;
if (packet->cseq_inconsistency) return TRUE;
}
return FALSE;
}
static void check_frame_partitions_list(Vp8RtpFmtUnpackerCtx *ctx, Vp8RtpFmtFrame *frame) {
Vp8RtpFmtPartition *partition;
uint32_t last_cseq;
int i;
bool_t gap = FALSE;
if (frame->partitions[0] == NULL) {
mark_frame_as_invalid(ctx, frame);
......@@ -549,14 +549,8 @@ static void check_frame_partitions_list(Vp8RtpFmtUnpackerCtx *ctx, Vp8RtpFmtFram
mark_frame_as_invalid(ctx, frame);
return;
}
packet = (Vp8RtpFmtPacket *)ms_list_nth_data(frame->partitions[0]->packets_list, 0);
last_cseq = packet->extended_cseq;
for (i = 1; i < ms_list_size(frame->partitions[0]->packets_list); i++) {
packet = (Vp8RtpFmtPacket *)ms_list_nth_data(frame->partitions[0]->packets_list, i);
if (packet->extended_cseq != (last_cseq + 1)) gap = TRUE;
last_cseq = packet->extended_cseq;
}
if (gap == TRUE) {
if (has_sequence_inconsistency(frame->partitions[0]->packets_list)) {
mark_frame_as_invalid(ctx, frame);
return;
}
......@@ -586,14 +580,7 @@ static void check_frame_partitions_list(Vp8RtpFmtUnpackerCtx *ctx, Vp8RtpFmtFram
if ((partition == NULL) || !partition->has_start || !partition->has_marker) {
mark_frame_as_incomplete(ctx, frame, frame->partitions_info.nb_partitions);
} else {
packet = (Vp8RtpFmtPacket *)ms_list_nth_data(partition->packets_list, 0);
last_cseq = packet->extended_cseq;
for (i = 1; i < ms_list_size(partition->packets_list); i++) {
packet = (Vp8RtpFmtPacket *)ms_list_nth_data(partition->packets_list, i);
if (packet->extended_cseq != (last_cseq + 1)) gap = TRUE;
last_cseq = packet->extended_cseq;
}
if (gap == TRUE) {
if (has_sequence_inconsistency(partition->packets_list)){
mark_frame_as_incomplete(ctx, frame, frame->partitions_info.nb_partitions);
}
}
......@@ -628,23 +615,20 @@ static void add_frame(Vp8RtpFmtUnpackerCtx *ctx, MSList **packets_list) {
static void generate_frames_list(Vp8RtpFmtUnpackerCtx *ctx, MSList *packets_list) {
Vp8RtpFmtPacket *packet;
MSList *frame_packets_list = NULL;
int nb_packets;
MSList *it;
uint32_t ts;
int i;
/* If we have some packets from the previous iteration, put them in the frame_packets_list. */
nb_packets = ms_list_size(ctx->non_processed_packets_list);
for (i = 0; i < nb_packets; i++) {
packet = ms_list_nth_data(ctx->non_processed_packets_list, i);
for (it=ctx->non_processed_packets_list; it!=NULL; it=it->next) {
packet = (Vp8RtpFmtPacket*) it->data;
frame_packets_list = ms_list_append(frame_packets_list, packet);
}
ms_list_free(ctx->non_processed_packets_list);
ctx->non_processed_packets_list = NULL;
/* Process newly received packets. */
nb_packets = ms_list_size(packets_list);
for (i = 0; i < nb_packets; i++) {
packet = ms_list_nth_data(packets_list, i);
for (it=packets_list; it!=NULL; it=it->next) {
packet = (Vp8RtpFmtPacket*) it->data;
ts = mblk_get_timestamp_info(packet->m);
if ((ctx->initialized_last_ts == TRUE) && (ts != ctx->last_ts)) {
......@@ -665,15 +649,7 @@ static void generate_frames_list(Vp8RtpFmtUnpackerCtx *ctx, MSList *packets_list
}
/* If some packets are left, put them in a list for next iteration. */
nb_packets = ms_list_size(frame_packets_list);
for (i = 0; i < nb_packets; i++) {
packet = ms_list_nth_data(frame_packets_list, i);
ctx->non_processed_packets_list = ms_list_append(ctx->non_processed_packets_list, packet);
}
if (frame_packets_list != NULL){
ms_list_free(frame_packets_list);
}
ctx->non_processed_packets_list=frame_packets_list;
}
static void output_partition(MSQueue *out, Vp8RtpFmtPartition **partition, bool_t last) {
......@@ -896,7 +872,6 @@ void vp8rtpfmt_unpacker_init(Vp8RtpFmtUnpackerCtx *ctx, MSFilter *f, bool_t avpf
ctx->filter = f;
ctx->frames_list = NULL;
ctx->non_processed_packets_list = NULL;
ms_queue_init(&ctx->output_queue);
ctx->avpf_enabled = avpf_enabled;
ctx->freeze_on_error = freeze_on_error;
ctx->output_partitions = output_partitions;
......@@ -910,7 +885,6 @@ void vp8rtpfmt_unpacker_init(Vp8RtpFmtUnpackerCtx *ctx, MSFilter *f, bool_t avpf
void vp8rtpfmt_unpacker_uninit(Vp8RtpFmtUnpackerCtx *ctx) {
ms_list_free(ctx->frames_list);
ms_list_free(ctx->non_processed_packets_list);
ms_queue_flush(&ctx->output_queue);
}
void vp8rtpfmt_unpacker_process(Vp8RtpFmtUnpackerCtx *ctx, MSQueue *inout) {
......@@ -922,16 +896,26 @@ void vp8rtpfmt_unpacker_process(Vp8RtpFmtUnpackerCtx *ctx, MSQueue *inout) {
ms_message("vp8rtpfmt_unpacker_process:");
#endif
while ((m = ms_queue_get(inout)) != NULL) {
uint16_t cseq=mblk_get_cseq(m);
packet = ms_new0(Vp8RtpFmtPacket, 1);
packet->m = m;
packet->extended_cseq = vp8rtpfmt_unpacker_calc_extended_cseq(ctx, mblk_get_cseq(m));
packet->pd = ms_new0(Vp8RtpFmtPayloadDescriptor, 1);
if (m->b_cont) msgpullup(m, -1);
packet->error = parse_payload_descriptor(packet);
packets_list = ms_list_insert_sorted(packets_list, (void *)packet, cseq_compare);
if (!ctx->initialized_ref_cseq){
ctx->initialized_ref_cseq=TRUE;
ctx->ref_cseq=cseq;
}else{
ctx->ref_cseq++;
if (ctx->ref_cseq!=cseq){
packet->cseq_inconsistency=TRUE;
ms_message("sequence inconsistency detected (diff=%i)",(int)(cseq-ctx->ref_cseq));
ctx->ref_cseq=cseq;
}
}
packets_list=ms_list_append(packets_list,packet);
}
generate_frames_list(ctx, packets_list);
ms_list_free(packets_list);
#ifdef VP8RTPFMT_DEBUG
......@@ -949,40 +933,6 @@ void vp8rtpfmt_unpacker_process(Vp8RtpFmtUnpackerCtx *ctx, MSQueue *inout) {
}
}
uint32_t vp8rtpfmt_unpacker_calc_extended_cseq(Vp8RtpFmtUnpackerCtx *ctx, uint16_t cseq) {
uint32_t extended_cseq;
uint32_t cseq_a;
uint32_t cseq_b;
uint32_t diff_a;
uint32_t diff_b;
if (ctx->initialized_ref_cseq != TRUE) {
ctx->ref_cseq = cseq | 0x80000000;
ctx->initialized_ref_cseq = TRUE;
extended_cseq = ctx->ref_cseq;
} else {
cseq_a = cseq | (ctx->ref_cseq & 0xFFFF0000);
if (ctx->ref_cseq < cseq_a) {
cseq_b = cseq_a - 0x00010000;
diff_a = cseq_a - ctx->ref_cseq;
diff_b = ctx->ref_cseq - cseq_b;
} else {
cseq_b = cseq_a + 0x00010000;
diff_a = ctx->ref_cseq - cseq_a;
diff_b = cseq_b - ctx->ref_cseq;
}
if (diff_a < diff_b) {
extended_cseq = cseq_a;
} else {
extended_cseq = cseq_b;
}
ctx->ref_cseq = extended_cseq;
}
return extended_cseq;
}
static void packer_process_frame_part(void *p, void *c) {
Vp8RtpFmtPacket *packet = (Vp8RtpFmtPacket *)p;
......
......@@ -62,8 +62,8 @@ extern "C"{
typedef struct Vp8RtpFmtPacket {
mblk_t *m;
Vp8RtpFmtPayloadDescriptor *pd;
uint32_t extended_cseq;
Vp8RtpFmtErrorCode error;
bool_t cseq_inconsistency;
} Vp8RtpFmtPacket;
typedef struct Vp8RtpFmtPartition {
......@@ -98,10 +98,9 @@ extern "C"{
MSFilter *filter;
MSList *frames_list;
MSList *non_processed_packets_list;
MSQueue output_queue;
MSVideoSize video_size;
uint32_t last_ts;
uint32_t ref_cseq;
uint16_t ref_cseq;
bool_t avpf_enabled;
bool_t freeze_on_error;
bool_t output_partitions;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment