summaryrefslogtreecommitdiff
path: root/toxav
diff options
context:
space:
mode:
authornotsecure <notsecure@marek.ca>2014-06-23 14:43:39 -0400
committernotsecure <notsecure@marek.ca>2014-06-23 14:48:30 -0400
commit4e7593a09cf3684884ab5c86de74fbf17bba3250 (patch)
tree1a9a769df5cfd342bac916dc0929e69798a99df2 /toxav
parent139cfa7aebae49cadd14af875a8c0b52fc614877 (diff)
basic packet splitting for video frames
Diffstat (limited to 'toxav')
-rw-r--r--toxav/toxav.c96
1 files changed, 83 insertions, 13 deletions
diff --git a/toxav/toxav.c b/toxav/toxav.c
index 742898ea..a5ea4ed4 100644
--- a/toxav/toxav.c
+++ b/toxav/toxav.c
@@ -40,6 +40,9 @@
40/* Assume 60 fps*/ 40/* Assume 60 fps*/
41#define MAX_ENCODE_TIME_US ((1000 / 60) * 1000) 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#define inline__ inline __attribute__((always_inline)) 47#define inline__ inline __attribute__((always_inline))
45 48
@@ -58,6 +61,10 @@ typedef struct _CallSpecific {
58 * reuse them really. 61 * reuse them really.
59 */ 62 */
60 JitterBuffer *j_buf; /** Jitter buffer for audio */ 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} CallSpecific; 68} CallSpecific;
62 69
63 70
@@ -324,6 +331,16 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin
324 LOGGER_ERROR("Error while starting video RTP session!\n"); 331 LOGGER_ERROR("Error while starting video RTP session!\n");
325 return ErrorStartingVideoRtp; 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 if ( !(call->j_buf = create_queue(codec_settings->jbuf_capacity)) ) return ErrorInternal; 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 * @retval -1 Failure. 412 * @retval -1 Failure.
396 */ 413 */
397inline__ int toxav_send_rtp_payload ( ToxAv *av, int32_t call_index, ToxAvCallType type, const uint8_t *payload, 414inline__ 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 if (cii(call_index, av->msi_session)) return ErrorNoCall; 417 if (cii(call_index, av->msi_session)) return ErrorNoCall;
401 418
402 if ( av->calls[call_index].crtps[type - TypeAudio] ) 419#define send(data, len) rtp_send_msg(av->calls[call_index].crtps[type - TypeAudio], av->msi_session->messenger_handle, data, len)
403 return rtp_send_msg ( av->calls[call_index].crtps[type - TypeAudio], av->msi_session->messenger_handle, payload, 420
404 length ); 421 if (av->calls[call_index].crtps[type - TypeAudio]) {
405 else return -1; 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 uint8_t packet [RTP_PAYLOAD_SIZE]; 527 uint8_t packet [RTP_PAYLOAD_SIZE];
478 CallSpecific *call = &av->calls[call_index]; 528 CallSpecific *call = &av->calls[call_index];
479 529
480 int recved_size = 0; 530 int recved_size;
481 531 while((recved_size = toxav_recv_rtp_payload(av, call_index, TypeVideo, packet)) > 0) {
482 do { 532 if(recved_size < 3) {
483 recved_size = toxav_recv_rtp_payload(av, call_index, TypeVideo, packet); 533 continue;
484 534 }
485 if (recved_size > 0) {
486 int rc = vpx_codec_decode(&call->cs->v_decoder, packet, recved_size, NULL, 0);
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 if (rc != VPX_CODEC_OK) { 545 if (rc != VPX_CODEC_OK) {
489 LOGGER_ERROR("Error decoding video: %s\n", vpx_codec_err_to_string(rc)); 546 LOGGER_ERROR("Error decoding video: %s\n", vpx_codec_err_to_string(rc));
490 return ErrorInternal; 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 vpx_codec_iter_t iter = NULL; 566 vpx_codec_iter_t iter = NULL;
497 vpx_image_t *img; 567 vpx_image_t *img;