/** * @brief Receive decoded audio frame. * * @param av Handler. * @param frame_size The size of dest in frames/samples (one frame/sample is 16 bits or 2 bytes * and corresponds to one sample of audio.) * @param dest Destination of the raw audio (16 bit signed pcm with AUDIO_CHANNELS channels). * Make sure it has enough space for frame_size frames/samples. * @return int * @retval >=0 Size of received data in frames/samples. * @retval ToxAvError On error. */ inline__ int toxav_recv_audio ( ToxAv *av, int32_t call_index, int frame_size, int16_t *dest ) { if ( !dest ) return ErrorInternal; if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) { LOGGER_WARNING("Action on inactive call: %d", call_index); return ErrorNoCall; } CallSpecific *call = &av->calls[call_index]; uint8_t packet [RTP_PAYLOAD_SIZE]; int recved_size = toxav_recv_rtp_payload(av, call_index, TypeAudio, packet); if ( recved_size == ErrorAudioPacketLost ) { int dec_size = opus_decode(call->cs->audio_decoder, NULL, 0, dest, frame_size, 1); if ( dec_size < 0 ) { LOGGER_WARNING("Decoding error: %s", opus_strerror(dec_size)); return ErrorInternal; } else return dec_size; } else if ( recved_size ) { int dec_size = opus_decode(call->cs->audio_decoder, packet, recved_size, dest, frame_size, 0); if ( dec_size < 0 ) { LOGGER_WARNING("Decoding error: %s", opus_strerror(dec_size)); return ErrorInternal; } else return dec_size; } else { return 0; /* Nothing received */ } }
/** * @brief Receive decoded video packet. * * @param av Handler. * @param output Storage. * @return int * @retval 0 Success. * @retval ToxAvError On Error. */ inline__ int toxav_recv_video ( ToxAv *av, int32_t call_index, vpx_image_t **output) { if ( !output ) return ErrorInternal; uint8_t packet [RTP_PAYLOAD_SIZE]; int recved_size = 0; int rc; CallSpecific *call = &av->calls[call_index]; do { recved_size = toxav_recv_rtp_payload(av, call_index, TypeVideo, packet); if (recved_size > 0 && ( rc = vpx_codec_decode(&call->cs->v_decoder, packet, recved_size, NULL, 0) ) != VPX_CODEC_OK) { /*fprintf(stderr, "Error decoding video: %s\n", vpx_codec_err_to_string(rc));*/ return ErrorInternal; } } while (recved_size > 0); vpx_codec_iter_t iter = NULL; vpx_image_t *img; img = vpx_codec_get_frame(&call->cs->v_decoder, &iter); *output = img; return 0; }
/** * @brief Receive decoded video packet. * * @param av Handler. * @param output Storage. * @return int * @retval 0 Success. * @retval ToxAvError On Error. */ inline__ int toxav_recv_video ( ToxAv *av, vpx_image_t **output) { if ( !output ) return ErrorInternal; uint8_t packet [RTP_PAYLOAD_SIZE]; int recved_size = 0; int error; do { recved_size = toxav_recv_rtp_payload(av, TypeVideo, packet); if (recved_size > 0 && ( error = vpx_codec_decode(&av->cs->v_decoder, packet, recved_size, NULL, 0) ) != VPX_CODEC_OK) fprintf(stderr, "Error decoding: %s\n", vpx_codec_err_to_string(error)); } while (recved_size > 0); vpx_codec_iter_t iter = NULL; vpx_image_t *img; img = vpx_codec_get_frame(&av->cs->v_decoder, &iter); *output = img; return 0; /* Yeah, i set output to be NULL if nothing received */ }
/** * @brief Receive decoded audio frame. * * @param av Handler. * @param frame_size The size of dest in frames/samples (one frame/sample is 16 bits or 2 bytes * and corresponds to one sample of audio.) * @param dest Destination of the raw audio (16 bit signed pcm with AUDIO_CHANNELS channels). * Make sure it has enough space for frame_size frames/samples. * @return int * @retval >=0 Size of received data in frames/samples. * @retval ToxAvError On error. */ inline__ int toxav_recv_audio ( ToxAv *av, int frame_size, int16_t *dest ) { if ( !dest ) return ErrorInternal; uint8_t packet [RTP_PAYLOAD_SIZE]; int recved_size = toxav_recv_rtp_payload(av, TypeAudio, packet); if ( recved_size == ErrorAudioPacketLost ) { return opus_decode(av->cs->audio_decoder, NULL, 0, dest, frame_size, 1); } else if ( recved_size ) { return opus_decode(av->cs->audio_decoder, packet, recved_size, dest, frame_size, 0); } else { return 0; /* Nothing received */ } }
/** * @brief Receive decoded video packet. * * @param av Handler. * @param output Storage. * @return int * @retval 0 Success. * @retval ToxAvError On Error. */ inline__ int toxav_recv_video ( ToxAv *av, int32_t call_index, vpx_image_t **output) { if ( !output ) return ErrorInternal; if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) { LOGGER_WARNING("Action on inactive call: %d", call_index); return ErrorNoCall; } uint8_t packet [RTP_PAYLOAD_SIZE]; CallSpecific *call = &av->calls[call_index]; int recved_size; while ((recved_size = toxav_recv_rtp_payload(av, call_index, TypeVideo, packet)) > 0) { if (recved_size < VIDEOFRAME_HEADER_SIZE) { continue; } uint8_t i = packet[0] - call->frame_id; if (i == 0) { /* piece of current frame */ } else if (i > 0 && i < 128) { /* recieved a piece of a frame ahead, flush current frame and start reading this new frame */ int rc = vpx_codec_decode(&call->cs->v_decoder, call->frame_buf, call->frame_limit, NULL, 0); call->frame_id = packet[0]; memset(call->frame_buf, 0, call->frame_limit); call->frame_limit = 0; if (rc != VPX_CODEC_OK) { LOGGER_ERROR("Error decoding video: %u %s\n", i, vpx_codec_err_to_string(rc)); } } else { /* old packet, dont read */ LOGGER_DEBUG("Old packet: %u\n", i); continue; } if (packet[1] > (MAX_VIDEOFRAME_SIZE - VIDEOFRAME_PIECE_SIZE + 1) / VIDEOFRAME_PIECE_SIZE) { //TODO, fix this check? not sure /* packet out of buffer range */ continue; } LOGGER_DEBUG("Video Packet: %u %u\n", packet[0], packet[1]); memcpy(call->frame_buf + packet[1] * VIDEOFRAME_PIECE_SIZE, packet + VIDEOFRAME_HEADER_SIZE, recved_size - VIDEOFRAME_HEADER_SIZE); uint32_t limit = packet[1] * VIDEOFRAME_PIECE_SIZE + recved_size - VIDEOFRAME_HEADER_SIZE; if (limit > call->frame_limit) { call->frame_limit = limit; LOGGER_DEBUG("Limit: %u\n", call->frame_limit); } } vpx_codec_iter_t iter = NULL; vpx_image_t *img; img = vpx_codec_get_frame(&call->cs->v_decoder, &iter); *output = img; return 0; }