Skip to content

Commit 4e7593a

Browse files
committed
basic packet splitting for video frames
1 parent 139cfa7 commit 4e7593a

File tree

1 file changed

+83
-13
lines changed

1 file changed

+83
-13
lines changed

toxav/toxav.c

Lines changed: 83 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@
4040
/* Assume 60 fps*/
4141
#define MAX_ENCODE_TIME_US ((1000 / 60) * 1000)
4242

43+
#define MAX_VIDEOFRAME_SIZE 0x40000 /* 256KiB */
44+
#define VIDEOFRAME_PIECE_SIZE 0x500 /* 1.25 KiB*/
45+
4346

4447
#define inline__ inline __attribute__((always_inline))
4548

@@ -58,6 +61,10 @@ typedef struct _CallSpecific {
5861
* reuse them really.
5962
*/
6063
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 */
6168
} CallSpecific;
6269

6370

@@ -324,6 +331,16 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin
324331
LOGGER_ERROR("Error while starting video RTP session!\n");
325332
return ErrorStartingVideoRtp;
326333
}
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+
327344
}
328345

329346
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 )
395412
* @retval -1 Failure.
396413
*/
397414
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 )
399416
{
400417
if (cii(call_index, av->msi_session)) return ErrorNoCall;
401418

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
406456
}
407457

408458
/**
@@ -477,21 +527,41 @@ inline__ int toxav_recv_video ( ToxAv *av, int32_t call_index, vpx_image_t **out
477527
uint8_t packet [RTP_PAYLOAD_SIZE];
478528
CallSpecific *call = &av->calls[call_index];
479529

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+
}
487535

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;
488545
if (rc != VPX_CODEC_OK) {
489546
LOGGER_ERROR("Error decoding video: %s\n", vpx_codec_err_to_string(rc));
490547
return ErrorInternal;
491548
}
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;
492557
}
493558

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+
}
495565

496566
vpx_codec_iter_t iter = NULL;
497567
vpx_image_t *img;

0 commit comments

Comments
 (0)