summaryrefslogtreecommitdiff
path: root/toxav/codec.c
diff options
context:
space:
mode:
authormannol <eniz_vukovic@hotmail.com>2015-04-22 02:09:37 +0200
committermannol <eniz_vukovic@hotmail.com>2015-04-22 02:09:37 +0200
commit1bfd93e64a2a6d3bf9c90a9aa89abd29f3d826a7 (patch)
tree094af1cad749bef83678071476075160d956bfeb /toxav/codec.c
parent3fd0ee5f0873924b4881b0e33eb1c17ea877ab4a (diff)
Finished refactoring
Diffstat (limited to 'toxav/codec.c')
-rw-r--r--toxav/codec.c686
1 files changed, 0 insertions, 686 deletions
diff --git a/toxav/codec.c b/toxav/codec.c
deleted file mode 100644
index 57e43c67..00000000
--- a/toxav/codec.c
+++ /dev/null
@@ -1,686 +0,0 @@
1/** codec.c
2 *
3 * Copyright (C) 2013-2015 Tox project All Rights Reserved.
4 *
5 * This file is part of Tox.
6 *
7 * Tox is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * Tox is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif /* HAVE_CONFIG_H */
26
27#include "../toxcore/logger.h"
28#include "../toxcore/util.h"
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <stdbool.h>
33#include <math.h>
34#include <assert.h>
35#include <time.h>
36
37#include "msi.h"
38#include "rtp.h"
39#include "codec.h"
40
41#define DEFAULT_JBUF 3
42
43/* Good quality encode. */
44#define MAX_DECODE_TIME_US 0
45
46#define MAX_VIDEOFRAME_SIZE 0x40000 /* 256KiB */
47#define VIDEOFRAME_HEADER_SIZE 0x2
48
49/* FIXME: Might not be enough? NOTE: I think it is enough */
50#define VIDEO_DECODE_BUFFER_SIZE 20
51
52#define ARRAY(TYPE__) struct { uint16_t size; TYPE__ data[]; }
53
54typedef ARRAY(uint8_t) Payload;
55
56/* JITTER BUFFER WORK */
57typedef struct JitterBuffer_s {
58 RTPMessage **queue;
59 uint32_t size;
60 uint32_t capacity;
61 uint16_t bottom;
62 uint16_t top;
63} JitterBuffer;
64
65static JitterBuffer *jbuf_new(uint32_t capacity)
66{
67 unsigned int size = 1;
68
69 while (size <= (capacity * 4)) {
70 size *= 2;
71 }
72
73 JitterBuffer *q;
74
75 if ( !(q = calloc(sizeof(JitterBuffer), 1)) ) return NULL;
76
77 if (!(q->queue = calloc(sizeof(RTPMessage *), size))) {
78 free(q);
79 return NULL;
80 }
81
82 q->size = size;
83 q->capacity = capacity;
84 return q;
85}
86
87static void jbuf_clear(JitterBuffer *q)
88{
89 for (; q->bottom != q->top; ++q->bottom) {
90 if (q->queue[q->bottom % q->size]) {
91 rtp_free_msg(NULL, q->queue[q->bottom % q->size]);
92 q->queue[q->bottom % q->size] = NULL;
93 }
94 }
95}
96
97static void jbuf_free(JitterBuffer *q)
98{
99 if (!q) return;
100
101 jbuf_clear(q);
102 free(q->queue);
103 free(q);
104}
105
106static int jbuf_write(JitterBuffer *q, RTPMessage *m)
107{
108 uint16_t sequnum = m->header->sequnum;
109
110 unsigned int num = sequnum % q->size;
111
112 if ((uint32_t)(sequnum - q->bottom) > q->size) {
113 LOGGER_DEBUG("Clearing filled jitter buffer: %p", q);
114
115 jbuf_clear(q);
116 q->bottom = sequnum - q->capacity;
117 q->queue[num] = m;
118 q->top = sequnum + 1;
119 return 0;
120 }
121
122 if (q->queue[num])
123 return -1;
124
125 q->queue[num] = m;
126
127 if ((sequnum - q->bottom) >= (q->top - q->bottom))
128 q->top = sequnum + 1;
129
130 return 0;
131}
132
133/* success is set to 0 when there is nothing to dequeue,
134 * 1 when there's a good packet,
135 * 2 when there's a lost packet */
136static RTPMessage *jbuf_read(JitterBuffer *q, int32_t *success)
137{
138 if (q->top == q->bottom) {
139 *success = 0;
140 return NULL;
141 }
142
143 unsigned int num = q->bottom % q->size;
144
145 if (q->queue[num]) {
146 RTPMessage *ret = q->queue[num];
147 q->queue[num] = NULL;
148 ++q->bottom;
149 *success = 1;
150 return ret;
151 }
152
153 if ((uint32_t)(q->top - q->bottom) > q->capacity) {
154 ++q->bottom;
155 *success = 2;
156 return NULL;
157 }
158
159 *success = 0;
160 return NULL;
161}
162
163static int convert_bw_to_sampling_rate(int bw)
164{
165 switch(bw)
166 {
167 case OPUS_BANDWIDTH_NARROWBAND: return 8000;
168 case OPUS_BANDWIDTH_MEDIUMBAND: return 12000;
169 case OPUS_BANDWIDTH_WIDEBAND: return 16000;
170 case OPUS_BANDWIDTH_SUPERWIDEBAND: return 24000;
171 case OPUS_BANDWIDTH_FULLBAND: return 48000;
172 default: return -1;
173 }
174}
175
176OpusEncoder* create_audio_encoder (int32_t bitrate, int32_t sampling_rate, int32_t channel_count)
177{
178 int status = OPUS_OK;
179 OpusEncoder* rc = opus_encoder_create(sampling_rate, channel_count, OPUS_APPLICATION_AUDIO, &status);
180
181 if ( status != OPUS_OK ) {
182 LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(status));
183 return NULL;
184 }
185
186 status = opus_encoder_ctl(rc, OPUS_SET_BITRATE(bitrate));
187
188 if ( status != OPUS_OK ) {
189 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(status));
190 goto FAILURE;
191 }
192
193 status = opus_encoder_ctl(rc, OPUS_SET_COMPLEXITY(10));
194
195 if ( status != OPUS_OK ) {
196 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(status));
197 goto FAILURE;
198 }
199
200 return rc;
201
202FAILURE:
203 opus_encoder_destroy(rc);
204 return NULL;
205}
206
207bool create_video_encoder (vpx_codec_ctx_t* dest, int32_t bitrate)
208{
209 assert(dest);
210
211 vpx_codec_enc_cfg_t cfg;
212 int rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0);
213
214 if (rc != VPX_CODEC_OK) {
215 LOGGER_ERROR("Failed to get config: %s", vpx_codec_err_to_string(rc));
216 return false;
217 }
218
219 rc = vpx_codec_enc_init_ver(dest, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0,
220 VPX_ENCODER_ABI_VERSION);
221
222 if ( rc != VPX_CODEC_OK) {
223 LOGGER_ERROR("Failed to initialize encoder: %s", vpx_codec_err_to_string(rc));
224 return false;
225 }
226
227 cfg.rc_target_bitrate = bitrate;
228 cfg.g_w = 800;
229 cfg.g_h = 600;
230 cfg.g_pass = VPX_RC_ONE_PASS;
231 cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT | VPX_ERROR_RESILIENT_PARTITIONS;
232 cfg.g_lag_in_frames = 0;
233 cfg.kf_min_dist = 0;
234 cfg.kf_max_dist = 48;
235 cfg.kf_mode = VPX_KF_AUTO;
236
237 rc = vpx_codec_control(dest, VP8E_SET_CPUUSED, 8);
238
239 if ( rc != VPX_CODEC_OK) {
240 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));
241 vpx_codec_destroy(dest);
242 }
243
244 return true;
245}
246
247bool reconfigure_audio_decoder(CSession* cs, int32_t sampling_rate, int8_t channels)
248{
249 if (sampling_rate != cs->last_decoding_sampling_rate || channels != cs->last_decoding_channel_count) {
250 if (current_time_monotonic() - cs->last_decoder_reconfiguration < 500)
251 return false;
252
253 int status;
254 OpusDecoder* new_dec = opus_decoder_create(sampling_rate, channels, &status );
255 if ( status != OPUS_OK ) {
256 LOGGER_ERROR("Error while starting audio decoder(%d %d): %s", sampling_rate, channels, opus_strerror(status));
257 return false;
258 }
259
260 cs->last_decoding_sampling_rate = sampling_rate;
261 cs->last_decoding_channel_count = channels;
262 cs->last_decoder_reconfiguration = current_time_monotonic();
263
264 opus_decoder_destroy(cs->audio_decoder);
265 cs->audio_decoder = new_dec;
266
267 LOGGER_DEBUG("Reconfigured audio decoder sr: %d cc: %d", sampling_rate, channels);
268 }
269
270 return true;
271}
272
273/* PUBLIC */
274void cs_do(CSession *cs)
275{
276 /* Codec session should always be protected by call mutex so no need to check for cs validity
277 */
278
279 if (!cs)
280 return;
281
282 Payload *p;
283 int rc;
284
285 int success = 0;
286
287 LOGGED_LOCK(cs->queue_mutex);
288
289 /********************* AUDIO *********************/
290 if (cs->audio_decoder) {
291 RTPMessage *msg;
292
293 /* The maximum for 120 ms 48 KHz audio */
294 int16_t tmp[5760];
295
296 while ((msg = jbuf_read(cs->j_buf, &success)) || success == 2) {
297 LOGGED_UNLOCK(cs->queue_mutex);
298
299 if (success == 2) {
300 LOGGER_DEBUG("OPUS correction");
301 rc = opus_decode(cs->audio_decoder, NULL, 0, tmp,
302 (cs->last_packet_sampling_rate * cs->last_packet_frame_duration / 1000) /
303 cs->last_packet_channel_count, 1);
304 } else {
305 /* Get values from packet and decode. */
306 /* NOTE: This didn't work very well
307 rc = convert_bw_to_sampling_rate(opus_packet_get_bandwidth(msg->data));
308 if (rc != -1) {
309 cs->last_packet_sampling_rate = rc;
310 } else {
311 LOGGER_WARNING("Failed to load packet values!");
312 rtp_free_msg(NULL, msg);
313 continue;
314 }*/
315
316
317 /* Pick up sampling rate from packet */
318 memcpy(&cs->last_packet_sampling_rate, msg->data, 4);
319 cs->last_packet_sampling_rate = ntohl(cs->last_packet_sampling_rate);
320
321 cs->last_packet_channel_count = opus_packet_get_nb_channels(msg->data + 4);
322
323 /*
324 * NOTE: even though OPUS supports decoding mono frames with stereo decoder and vice versa,
325 * it didn't work quite well.
326 */
327 if (!reconfigure_audio_decoder(cs, cs->last_packet_sampling_rate, cs->last_packet_channel_count)) {
328 LOGGER_WARNING("Failed to reconfigure decoder!");
329 rtp_free_msg(NULL, msg);
330 continue;
331 }
332
333 rc = opus_decode(cs->audio_decoder, msg->data + 4, msg->length - 4, tmp, 5760, 0);
334 rtp_free_msg(NULL, msg);
335 }
336
337 if (rc < 0) {
338 LOGGER_WARNING("Decoding error: %s", opus_strerror(rc));
339 } else if (cs->acb.first) {
340 cs->last_packet_frame_duration = (rc * 1000) / cs->last_packet_sampling_rate * cs->last_packet_channel_count;
341
342 cs->acb.first(cs->av, cs->friend_id, tmp, rc * cs->last_packet_channel_count,
343 cs->last_packet_channel_count, cs->last_packet_sampling_rate, cs->acb.second);
344
345 }
346
347 LOGGED_LOCK(cs->queue_mutex);
348 }
349 }
350
351 /********************* VIDEO *********************/
352 if (cs->vbuf_raw && !rb_empty(cs->vbuf_raw)) {
353 /* Decode video */
354 rb_read(cs->vbuf_raw, (void**)&p);
355
356 /* Leave space for (possibly) other thread to queue more data after we read it here */
357 LOGGED_UNLOCK(cs->queue_mutex);
358
359 rc = vpx_codec_decode(cs->v_decoder, p->data, p->size, NULL, MAX_DECODE_TIME_US);
360 free(p);
361
362 if (rc != VPX_CODEC_OK) {
363 LOGGER_ERROR("Error decoding video: %s", vpx_codec_err_to_string(rc));
364 } else {
365 vpx_codec_iter_t iter = NULL;
366 vpx_image_t *dest = vpx_codec_get_frame(cs->v_decoder, &iter);
367
368 /* Play decoded images */
369 for (; dest; dest = vpx_codec_get_frame(cs->v_decoder, &iter)) {
370 if (cs->vcb.first)
371 cs->vcb.first(cs->av, cs->friend_id, dest->d_w, dest->d_h,
372 (const uint8_t*)dest->planes[0], (const uint8_t*)dest->planes[1], (const uint8_t*)dest->planes[2],
373 dest->stride[0], dest->stride[1], dest->stride[2], cs->vcb.second);
374
375 vpx_img_free(dest);
376 }
377 }
378
379 return;
380 }
381
382 LOGGED_UNLOCK(cs->queue_mutex);
383}
384CSession *cs_new(uint32_t peer_video_frame_piece_size)
385{
386 CSession *cs = calloc(sizeof(CSession), 1);
387
388 if (!cs) {
389 LOGGER_WARNING("Allocation failed! Application might misbehave!");
390 return NULL;
391 }
392
393 if (create_recursive_mutex(cs->queue_mutex) != 0) {
394 LOGGER_WARNING("Failed to create recursive mutex!");
395 free(cs);
396 return NULL;
397 }
398
399 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
400 /* Create decoders and set up their values
401 */
402
403 /*
404 * AUDIO
405 */
406
407 int status;
408 cs->audio_decoder = opus_decoder_create(48000, 2, &status );
409
410 if ( status != OPUS_OK ) {
411 LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(status));
412 goto FAILURE;
413 }
414
415 cs->last_decoding_channel_count = 2;
416 cs->last_decoding_sampling_rate = 48000;
417 cs->last_decoder_reconfiguration = 0; /* Make it possible to reconfigure straight away */
418
419 /* These need to be set in order to properly
420 * do error correction with opus */
421 cs->last_packet_frame_duration = 120;
422 cs->last_packet_sampling_rate = 48000;
423
424 if ( !(cs->j_buf = jbuf_new(DEFAULT_JBUF)) ) {
425 LOGGER_WARNING("Jitter buffer creaton failed!");
426 opus_decoder_destroy(cs->audio_decoder);
427 goto FAILURE;
428 }
429
430 /*
431 * VIDEO
432 */
433 int rc = vpx_codec_dec_init_ver(cs->v_decoder, VIDEO_CODEC_DECODER_INTERFACE,
434 NULL, 0, VPX_DECODER_ABI_VERSION);
435
436 if ( rc != VPX_CODEC_OK) {
437 LOGGER_ERROR("Init video_decoder failed: %s", vpx_codec_err_to_string(rc));
438 goto AUDIO_DECODER_CLEANUP;
439 }
440
441 if ( !(cs->frame_buf = calloc(MAX_VIDEOFRAME_SIZE, 1)) ) {
442 vpx_codec_destroy(cs->v_decoder);
443 goto AUDIO_DECODER_CLEANUP;
444 }
445
446 if ( !(cs->vbuf_raw = rb_new(VIDEO_DECODE_BUFFER_SIZE)) ) {
447 free(cs->frame_buf);
448 vpx_codec_destroy(cs->v_decoder);
449 goto AUDIO_DECODER_CLEANUP;
450 }
451
452 if ( !(cs->split_video_frame = calloc(VIDEOFRAME_PIECE_SIZE + VIDEOFRAME_HEADER_SIZE, 1)) )
453 goto FAILURE;
454
455 cs->linfts = current_time_monotonic();
456 cs->lcfd = 60;
457 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
458
459 /* Initialize encoders with default values */
460 cs->audio_encoder = create_audio_encoder(48000, 48000, 2);
461 if (cs->audio_encoder == NULL)
462 goto VIDEO_DECODER_CLEANUP;
463
464 cs->last_encoding_bitrate = 48000;
465 cs->last_encoding_sampling_rate = 48000;
466 cs->last_encoding_channel_count = 2;
467
468 if (!create_video_encoder(cs->v_encoder, 500000)) {
469 opus_encoder_destroy(cs->audio_encoder);
470 goto VIDEO_DECODER_CLEANUP;
471 }
472
473 cs->peer_video_frame_piece_size = peer_video_frame_piece_size;
474
475 return cs;
476
477VIDEO_DECODER_CLEANUP:
478 rb_free(cs->vbuf_raw);
479 free(cs->frame_buf);
480 vpx_codec_destroy(cs->v_decoder);
481AUDIO_DECODER_CLEANUP:
482 opus_decoder_destroy(cs->audio_decoder);
483 jbuf_free(cs->j_buf);
484FAILURE:
485 pthread_mutex_destroy(cs->queue_mutex);
486 free(cs);
487 return NULL;
488}
489void cs_kill(CSession *cs)
490{
491 if (!cs)
492 return;
493
494 /* NOTE: queue_message() will not be called since
495 * the callback is unregistered before cs_kill is called.
496 */
497
498 opus_encoder_destroy(cs->audio_encoder);
499 opus_decoder_destroy(cs->audio_decoder);
500 jbuf_free(cs->j_buf);
501 vpx_codec_destroy(cs->v_encoder);
502 vpx_codec_destroy(cs->v_decoder);
503 rb_free(cs->vbuf_raw);
504 free(cs->frame_buf);
505 free(cs->split_video_frame);
506
507 pthread_mutex_destroy(cs->queue_mutex);
508
509 LOGGER_DEBUG("Terminated codec state: %p", cs);
510 free(cs);
511}
512void cs_init_video_splitter_cycle(CSession* cs)
513{
514 cs->split_video_frame[0] = cs->frameid_out++;
515 cs->split_video_frame[1] = 0;
516}
517int cs_update_video_splitter_cycle(CSession *cs, const uint8_t *payload, uint16_t length)
518{
519 cs->processing_video_frame = payload;
520 cs->processing_video_frame_size = length;
521
522 return ((length - 1) / VIDEOFRAME_PIECE_SIZE) + 1;
523}
524const uint8_t *cs_iterate_split_video_frame(CSession *cs, uint16_t *size)
525{
526 if (!cs || !size) return NULL;
527
528 if (cs->processing_video_frame_size > VIDEOFRAME_PIECE_SIZE) {
529 memcpy(cs->split_video_frame + VIDEOFRAME_HEADER_SIZE,
530 cs->processing_video_frame,
531 VIDEOFRAME_PIECE_SIZE);
532
533 cs->processing_video_frame += VIDEOFRAME_PIECE_SIZE;
534 cs->processing_video_frame_size -= VIDEOFRAME_PIECE_SIZE;
535
536 *size = VIDEOFRAME_PIECE_SIZE + VIDEOFRAME_HEADER_SIZE;
537 } else {
538 memcpy(cs->split_video_frame + VIDEOFRAME_HEADER_SIZE,
539 cs->processing_video_frame,
540 cs->processing_video_frame_size);
541
542 *size = cs->processing_video_frame_size + VIDEOFRAME_HEADER_SIZE;
543 }
544
545 cs->split_video_frame[1]++;
546
547 return cs->split_video_frame;
548}
549int cs_reconfigure_video_encoder(CSession* cs, int32_t bitrate, uint16_t width, uint16_t height)
550{
551 vpx_codec_enc_cfg_t cfg = *cs->v_encoder[0].config.enc;
552 if (cfg.rc_target_bitrate == bitrate && cfg.g_w == width && cfg.g_h == height)
553 return 0; /* Nothing changed */
554
555 cfg.rc_target_bitrate = bitrate;
556 cfg.g_w = width;
557 cfg.g_h = height;
558
559 int rc = vpx_codec_enc_config_set(cs->v_encoder, &cfg);
560 if ( rc != VPX_CODEC_OK) {
561 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));
562 return -1;
563 }
564
565 return 0;
566}
567int cs_reconfigure_audio_encoder(CSession* cs, int32_t bitrate, int32_t sampling_rate, uint8_t channels)
568{
569 /* Values are checked in toxav.c */
570
571 if (cs->last_encoding_sampling_rate != sampling_rate || cs->last_encoding_channel_count != channels) {
572 OpusEncoder* new_encoder = create_audio_encoder(bitrate, sampling_rate, channels);
573 if (new_encoder == NULL)
574 return -1;
575
576 opus_encoder_destroy(cs->audio_encoder);
577 cs->audio_encoder = new_encoder;
578 } else if (cs->last_encoding_bitrate == bitrate)
579 return 0; /* Nothing changed */
580 else {
581 int status = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(bitrate));
582
583 if ( status != OPUS_OK ) {
584 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(status));
585 return -1;
586 }
587 }
588
589 cs->last_encoding_bitrate = bitrate;
590 cs->last_encoding_sampling_rate = sampling_rate;
591 cs->last_encoding_channel_count = channels;
592
593 LOGGER_DEBUG ("Reconfigured audio encoder br: %d sr: %d cc:%d", bitrate, sampling_rate, channels);
594 return 0;
595}
596/* Called from RTP */
597void queue_message(RTPSession *session, RTPMessage *msg)
598{
599 CSession *cs = session->cs;
600
601 if (!cs)
602 return;
603
604 /* Audio */
605 if (session->payload_type == rtp_TypeAudio % 128) {
606 LOGGED_LOCK(cs->queue_mutex);
607 int ret = jbuf_write(cs->j_buf, msg);
608 LOGGED_UNLOCK(cs->queue_mutex);
609
610 if (ret == -1) {
611 rtp_free_msg(NULL, msg);
612 }
613 }
614 /* Video */
615 else {
616 uint8_t *packet = msg->data;
617 uint32_t packet_size = msg->length;
618
619 if (packet_size < VIDEOFRAME_HEADER_SIZE)
620 goto end;
621
622 uint8_t diff = packet[0] - cs->frameid_in;
623
624 if (diff != 0) {
625 if (diff < 225) { /* New frame */
626 /* Flush last frames' data and get ready for this frame */
627 Payload *p = malloc(sizeof(Payload) + cs->frame_size);
628
629 if (p) {
630 LOGGED_LOCK(cs->queue_mutex);
631
632 if (rb_full(cs->vbuf_raw)) {
633 LOGGER_DEBUG("Dropped video frame");
634 Payload *tp;
635 rb_read(cs->vbuf_raw, (void**)&tp);
636 free(tp);
637 } else {
638 p->size = cs->frame_size;
639 memcpy(p->data, cs->frame_buf, cs->frame_size);
640 }
641
642 /* Calculate time took for peer to send us this frame */
643 uint32_t t_lcfd = current_time_monotonic() - cs->linfts;
644 cs->lcfd = t_lcfd > 100 ? cs->lcfd : t_lcfd;
645 cs->linfts = current_time_monotonic();
646
647 rb_write(cs->vbuf_raw, p);
648 LOGGED_UNLOCK(cs->queue_mutex);
649 } else {
650 LOGGER_WARNING("Allocation failed! Program might misbehave!");
651 goto end;
652 }
653
654 cs->frameid_in = packet[0];
655 memset(cs->frame_buf, 0, cs->frame_size);
656 cs->frame_size = 0;
657
658 } else { /* Old frame; drop */
659 LOGGER_DEBUG("Old packet: %u", packet[0]);
660 goto end;
661 }
662 }
663
664 uint8_t piece_number = packet[1];
665
666 uint32_t length_before_piece = ((piece_number - 1) * cs->peer_video_frame_piece_size);
667 uint32_t framebuf_new_length = length_before_piece + (packet_size - VIDEOFRAME_HEADER_SIZE);
668
669 if (framebuf_new_length > MAX_VIDEOFRAME_SIZE) {
670 goto end;
671 }
672
673 /* Otherwise it's part of the frame so just process */
674 /* LOGGER_DEBUG("Video Packet: %u %u", packet[0], packet[1]); */
675
676 memcpy(cs->frame_buf + length_before_piece,
677 packet + VIDEOFRAME_HEADER_SIZE,
678 packet_size - VIDEOFRAME_HEADER_SIZE);
679
680 if (framebuf_new_length > cs->frame_size)
681 cs->frame_size = framebuf_new_length;
682
683end:
684 rtp_free_msg(NULL, msg);
685 }
686}