diff options
author | notsecure <notsecure@marek.ca> | 2014-06-23 14:43:39 -0400 |
---|---|---|
committer | notsecure <notsecure@marek.ca> | 2014-06-23 14:48:30 -0400 |
commit | 4e7593a09cf3684884ab5c86de74fbf17bba3250 (patch) | |
tree | 1a9a769df5cfd342bac916dc0929e69798a99df2 /toxav | |
parent | 139cfa7aebae49cadd14af875a8c0b52fc614877 (diff) |
basic packet splitting for video frames
Diffstat (limited to 'toxav')
-rw-r--r-- | toxav/toxav.c | 96 |
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 | */ |
397 | inline__ int toxav_send_rtp_payload ( ToxAv *av, int32_t call_index, ToxAvCallType type, const uint8_t *payload, | 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 | 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; |