예제 #1
0
파일: toxav.c 프로젝트: buptfeifei/toxcore
/**
 * @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 */
    }
}
예제 #2
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, 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;
}
예제 #3
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
     */
}
예제 #4
0
/**
 * @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 */
    }
}
예제 #5
0
파일: toxav.c 프로젝트: buptfeifei/toxcore
/**
 * @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;
}