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