40
40
/* Assume 60 fps*/
41
41
#define MAX_ENCODE_TIME_US ((1000 / 60) * 1000)
42
42
43
+ #define MAX_VIDEOFRAME_SIZE 0x40000 /* 256KiB */
44
+ #define VIDEOFRAME_PIECE_SIZE 0x500 /* 1.25 KiB*/
45
+ #define VIDEOFRAME_HEADER_SIZE 0x2
46
+
43
47
44
48
#define inline__ inline __attribute__((always_inline))
45
49
@@ -58,6 +62,10 @@ typedef struct _CallSpecific {
58
62
* reuse them really.
59
63
*/
60
64
JitterBuffer * j_buf ; /** Jitter buffer for audio */
65
+
66
+ uint32_t frame_limit ; /* largest address written to in frame_buf for current input frame*/
67
+ uint8_t frame_id , frame_outid ; /* id of input and output video frame */
68
+ void * frame_buf ; /* buffer for split video payloads */
61
69
} CallSpecific ;
62
70
63
71
@@ -324,6 +332,17 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin
324
332
LOGGER_ERROR ("Error while starting video RTP session!\n" );
325
333
return ErrorStartingVideoRtp ;
326
334
}
335
+
336
+ call -> frame_limit = 0 ;
337
+ call -> frame_id = 0 ;
338
+ call -> frame_outid = 0 ;
339
+
340
+ call -> frame_buf = calloc (MAX_VIDEOFRAME_SIZE , 1 );
341
+
342
+ if (!call -> frame_buf ) {
343
+ return ErrorInternal ;
344
+ }
345
+
327
346
}
328
347
329
348
if ( !(call -> j_buf = create_queue (codec_settings -> jbuf_capacity )) ) return ErrorInternal ;
@@ -395,14 +414,51 @@ int toxav_kill_transmission ( ToxAv *av, int32_t call_index )
395
414
* @retval -1 Failure.
396
415
*/
397
416
inline__ int toxav_send_rtp_payload ( ToxAv * av , int32_t call_index , ToxAvCallType type , const uint8_t * payload ,
398
- uint16_t length )
417
+ unsigned int length )
399
418
{
400
419
if (cii (call_index , av -> msi_session )) return ErrorNoCall ;
401
420
402
- if ( av -> calls [call_index ].crtps [type - TypeAudio ] )
403
- return rtp_send_msg ( av -> calls [call_index ].crtps [type - TypeAudio ], av -> msi_session -> messenger_handle , payload ,
404
- length );
405
- else return -1 ;
421
+ #define send (data , len ) rtp_send_msg(av->calls[call_index].crtps[type - TypeAudio], av->msi_session->messenger_handle, data, len)
422
+
423
+ if (av -> calls [call_index ].crtps [type - TypeAudio ]) {
424
+ if (type == TypeAudio ) {
425
+ return send (payload , length );
426
+ } else {
427
+ if (length == 0 || length > MAX_VIDEOFRAME_SIZE ) {
428
+ LOGGER_ERROR ("Invalid video frame size: %u\n" , length );
429
+ return -1 ;
430
+ }
431
+
432
+ /* number of pieces - 1*/
433
+ uint8_t numparts = (length - 1 ) / VIDEOFRAME_PIECE_SIZE ;
434
+
435
+ uint8_t load [3 + VIDEOFRAME_PIECE_SIZE ];
436
+ load [0 ] = av -> calls [call_index ].frame_outid ++ ;
437
+ load [1 ] = 0 ;
438
+
439
+ int i ;
440
+
441
+ for (i = 0 ; i < numparts ; i ++ ) {
442
+ memcpy (load + VIDEOFRAME_HEADER_SIZE , payload , VIDEOFRAME_PIECE_SIZE );
443
+ payload += VIDEOFRAME_PIECE_SIZE ;
444
+
445
+ if (send (load , VIDEOFRAME_HEADER_SIZE + VIDEOFRAME_PIECE_SIZE ) != 0 ) {
446
+ return -1 ;
447
+ }
448
+
449
+ load [1 ]++ ;
450
+ }
451
+
452
+ /* remainder = length % VIDEOFRAME_PIECE_SIZE, VIDEOFRAME_PIECE_SIZE if = 0 */
453
+ length = ((length - 1 ) % VIDEOFRAME_PIECE_SIZE ) + 1 ;
454
+ memcpy (load + VIDEOFRAME_HEADER_SIZE , payload , length );
455
+ return send (load , VIDEOFRAME_HEADER_SIZE + length );
456
+ }
457
+ } else {
458
+ return -1 ;
459
+ }
460
+
461
+ #undef send
406
462
}
407
463
408
464
/**
@@ -477,21 +533,47 @@ inline__ int toxav_recv_video ( ToxAv *av, int32_t call_index, vpx_image_t **out
477
533
uint8_t packet [RTP_PAYLOAD_SIZE ];
478
534
CallSpecific * call = & av -> calls [call_index ];
479
535
480
- int recved_size = 0 ;
536
+ int recved_size ;
481
537
482
- do {
483
- recved_size = toxav_recv_rtp_payload (av , call_index , TypeVideo , packet );
538
+ while ((recved_size = toxav_recv_rtp_payload (av , call_index , TypeVideo , packet )) > 0 ) {
539
+ if (recved_size < VIDEOFRAME_HEADER_SIZE ) {
540
+ continue ;
541
+ }
542
+
543
+ uint8_t i = packet [0 ] - call -> frame_id ;
484
544
485
- if (recved_size > 0 ) {
486
- int rc = vpx_codec_decode (& call -> cs -> v_decoder , packet , recved_size , NULL , 0 );
545
+ if (i == 0 ) {
546
+ /* piece of current frame */
547
+ } else if (i > 0 && i < 128 ) {
548
+ /* recieved a piece of a frame ahead, flush current frame and start reading this new frame */
549
+ int rc = vpx_codec_decode (& call -> cs -> v_decoder , call -> frame_buf , call -> frame_limit , NULL , 0 );
550
+ call -> frame_id = packet [0 ];
551
+ memset (call -> frame_buf , 0 , call -> frame_limit );
552
+ call -> frame_limit = 0 ;
487
553
488
554
if (rc != VPX_CODEC_OK ) {
489
555
LOGGER_ERROR ("Error decoding video: %s\n" , vpx_codec_err_to_string (rc ));
490
556
return ErrorInternal ;
491
557
}
558
+ } else {
559
+ /* old packet, dont read */
560
+ continue ;
561
+ }
562
+
563
+ if (packet [1 ] > (MAX_VIDEOFRAME_SIZE - VIDEOFRAME_PIECE_SIZE + 1 ) /
564
+ VIDEOFRAME_PIECE_SIZE ) { //TODO, fix this check? not sure
565
+ /* packet out of buffer range */
566
+ continue ;
492
567
}
493
568
494
- } while (recved_size > 0 );
569
+ memcpy (call -> frame_buf + packet [1 ] * VIDEOFRAME_PIECE_SIZE , packet + VIDEOFRAME_HEADER_SIZE ,
570
+ recved_size - VIDEOFRAME_HEADER_SIZE );
571
+ uint32_t limit = packet [1 ] * VIDEOFRAME_PIECE_SIZE + recved_size - VIDEOFRAME_HEADER_SIZE ;
572
+
573
+ if (limit > call -> frame_limit ) {
574
+ call -> frame_limit = limit ;
575
+ }
576
+ }
495
577
496
578
vpx_codec_iter_t iter = NULL ;
497
579
vpx_image_t * img ;
0 commit comments