Recherche avancée

Médias (1)

Mot : - Tags -/école

Autres articles (62)

  • Les autorisations surchargées par les plugins

    27 avril 2010, par

    Mediaspip core
    autoriser_auteur_modifier() afin que les visiteurs soient capables de modifier leurs informations sur la page d’auteurs

  • Support de tous types de médias

    10 avril 2011

    Contrairement à beaucoup de logiciels et autres plate-formes modernes de partage de documents, MediaSPIP a l’ambition de gérer un maximum de formats de documents différents qu’ils soient de type : images (png, gif, jpg, bmp et autres...) ; audio (MP3, Ogg, Wav et autres...) ; vidéo (Avi, MP4, Ogv, mpg, mov, wmv et autres...) ; contenu textuel, code ou autres (open office, microsoft office (tableur, présentation), web (html, css), LaTeX, Google Earth) (...)

  • Support audio et vidéo HTML5

    10 avril 2011

    MediaSPIP utilise les balises HTML5 video et audio pour la lecture de documents multimedia en profitant des dernières innovations du W3C supportées par les navigateurs modernes.
    Pour les navigateurs plus anciens, le lecteur flash Flowplayer est utilisé.
    Le lecteur HTML5 utilisé a été spécifiquement créé pour MediaSPIP : il est complètement modifiable graphiquement pour correspondre à un thème choisi.
    Ces technologies permettent de distribuer vidéo et son à la fois sur des ordinateurs conventionnels (...)

Sur d’autres sites (8116)

  • FFMPEG Presentation Time Stamps (PTS) calculation in RTSP stream

    8 décembre 2020, par BadaBudaBudu

    Below please find en raw example of my code for your better understanding of what it does. Please note that this is an updated (removed deprecated methods, etc.) example code by myself from the official FFMPEG documentation complemented by my encoder.

    


    /// STD&#xA;#include <iostream>&#xA;#include <string>&#xA;&#xA;/// FFMPEG&#xA;extern "C"&#xA;{&#xA;    #include <libavformat></libavformat>avformat.h>&#xA;    #include <libswscale></libswscale>swscale.h>&#xA;    #include <libavutil></libavutil>imgutils.h>&#xA;}&#xA;&#xA;/// VideoLib&#xA;#include <tools></tools>multimediaprocessing.h>&#xA;#include &#xA;#include &#xA;#include <enums></enums>codec.h>&#xA;#include <enums></enums>pixelformat.h>&#xA;&#xA;/// OpenCV&#xA;#include <opencv2></opencv2>opencv.hpp>&#xA;&#xA;inline static const char *inputRtspAddress = "rtsp://192.168.0.186:8080/video/h264";&#xA;&#xA;int main()&#xA;{&#xA;    AVFormatContext* formatContext = nullptr;&#xA;&#xA;    AVStream* audioStream = nullptr;&#xA;    AVStream* videoStream = nullptr;&#xA;    AVCodec* audioCodec = nullptr;&#xA;    AVCodec* videoCodec = nullptr;&#xA;    AVCodecContext* audioCodecContext = nullptr;&#xA;    AVCodecContext* videoCodecContext = nullptr;&#xA;    vl::AudioSettings audioSettings;&#xA;    vl::VideoSettings videoSettings;&#xA;&#xA;    int audioIndex = -1;&#xA;    int videoIndex = -1;&#xA;&#xA;    SwsContext* swsContext = nullptr;&#xA;    std::vector frameBuffer;&#xA;    AVFrame* frame = av_frame_alloc();&#xA;    AVFrame* decoderFrame = av_frame_alloc();&#xA;&#xA;    AVPacket packet;&#xA;    cv::Mat mat;&#xA;&#xA;    vl::tools::MultimediaProcessing multimediaProcessing("rtsp://127.0.0.1:8080/stream", vl::configs::rtspStream, 0, vl::enums::EPixelFormat::ABGR);&#xA;&#xA;    // *** OPEN STREAM *** //&#xA;    if(avformat_open_input(&amp;formatContext, inputRtspAddress, nullptr, nullptr) &lt; 0)&#xA;    {&#xA;        std::cout &lt;&lt; "Failed to open input." &lt;&lt; std::endl;&#xA;        return EXIT_FAILURE;&#xA;    }&#xA;&#xA;    if(avformat_find_stream_info(formatContext, nullptr) &lt; 0)&#xA;    {&#xA;        std::cout &lt;&lt; "Failed to find stream info." &lt;&lt; std::endl;&#xA;        return EXIT_FAILURE;&#xA;    }&#xA;&#xA;    // *** FIND DECODER FOR BOTH AUDIO AND VIDEO STREAM *** //&#xA;    audioCodec = avcodec_find_decoder(AVCodecID::AV_CODEC_ID_AAC);&#xA;    videoCodec = avcodec_find_decoder(AVCodecID::AV_CODEC_ID_H264);&#xA;&#xA;    if(audioCodec == nullptr || videoCodec == nullptr)&#xA;    {&#xA;        std::cout &lt;&lt; "No AUDIO or VIDEO in stream." &lt;&lt; std::endl;&#xA;        return EXIT_FAILURE;&#xA;    }&#xA;&#xA;    // *** FIND STREAM FOR BOTH AUDIO AND VIDEO STREAM *** //&#xA;&#xA;    audioIndex = av_find_best_stream(formatContext, AVMEDIA_TYPE_AUDIO, -1, -1, &amp;audioCodec, 0);&#xA;    videoIndex = av_find_best_stream(formatContext, AVMEDIA_TYPE_VIDEO, -1, -1, &amp;videoCodec, 0);&#xA;&#xA;    if(audioIndex &lt; 0 || videoIndex &lt; 0)&#xA;    {&#xA;        std::cout &lt;&lt; "Failed to find AUDIO or VIDEO stream." &lt;&lt; std::endl;&#xA;        return EXIT_FAILURE;&#xA;    }&#xA;&#xA;    audioStream = formatContext->streams[audioIndex];&#xA;    videoStream = formatContext->streams[videoIndex];&#xA;&#xA;    // *** ALLOC CODEC CONTEXT FOR BOTH AUDIO AND VIDEO STREAM *** //&#xA;    audioCodecContext = avcodec_alloc_context3(audioCodec);&#xA;    videoCodecContext = avcodec_alloc_context3(videoCodec);&#xA;&#xA;    if(audioCodecContext == nullptr || videoCodecContext == nullptr)&#xA;    {&#xA;        std::cout &lt;&lt; "Can not allocate AUDIO or VIDEO context." &lt;&lt; std::endl;&#xA;        return EXIT_FAILURE;&#xA;    }&#xA;&#xA;    if(avcodec_parameters_to_context(audioCodecContext, formatContext->streams[audioIndex]->codecpar) &lt; 0 || avcodec_parameters_to_context(videoCodecContext, formatContext->streams[videoIndex]->codecpar) &lt; 0)&#xA;    {&#xA;        std::cout &lt;&lt; "Can not fill AUDIO or VIDEO codec context." &lt;&lt; std::endl;&#xA;        return EXIT_FAILURE;&#xA;    }&#xA;&#xA;    if(avcodec_open2(audioCodecContext, audioCodec, nullptr) &lt; 0 || avcodec_open2(videoCodecContext, videoCodec, nullptr) &lt; 0)&#xA;    {&#xA;        std::cout &lt;&lt; "Failed to open AUDIO codec" &lt;&lt; std::endl;&#xA;        return EXIT_FAILURE;&#xA;    }&#xA;&#xA;    // *** INITIALIZE MULTIMEDIA PROCESSING *** //&#xA;    std::vector<unsigned char="char"> extraData(audioStream->codecpar->extradata_size);&#xA;    std::copy_n(audioStream->codecpar->extradata, extraData.size(), extraData.begin());&#xA;&#xA;    audioSettings.sampleRate         = audioStream->codecpar->sample_rate,&#xA;    audioSettings.bitrate            = audioStream->codecpar->bit_rate,&#xA;    audioSettings.codec              = vl::enums::EAudioCodec::AAC,&#xA;    audioSettings.channels           = audioStream->codecpar->channels,&#xA;    audioSettings.bitsPerCodedSample = audioStream->codecpar->bits_per_coded_sample,&#xA;    audioSettings.bitsPerRawSample   = audioStream->codecpar->bits_per_raw_sample,&#xA;    audioSettings.blockAlign         = audioStream->codecpar->block_align,&#xA;    audioSettings.channelLayout      = audioStream->codecpar->channel_layout,&#xA;    audioSettings.format             = audioStream->codecpar->format,&#xA;    audioSettings.frameSize          = audioStream->codecpar->frame_size,&#xA;    audioSettings.codecExtraData     = std::move(extraData);&#xA;&#xA;    videoSettings.width              = 1920;&#xA;    videoSettings.height             = 1080;&#xA;    videoSettings.framerate          = 25;&#xA;    videoSettings.pixelFormat        = vl::enums::EPixelFormat::ARGB;&#xA;    videoSettings.bitrate            = 8000 * 1000;&#xA;    videoSettings.codec              = vl::enums::EVideoCodec::H264;&#xA;&#xA;    multimediaProcessing.initEncoder(videoSettings, audioSettings);&#xA;&#xA;    // *** INITIALIZE SWS CONTEXT *** //&#xA;    swsContext = sws_getCachedContext(nullptr, videoCodecContext->width, videoCodecContext->height, videoCodecContext->pix_fmt, videoCodecContext->width, videoCodecContext->height, AV_PIX_FMT_RGBA, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);&#xA;&#xA;    if (const auto inReturn = av_image_get_buffer_size(AV_PIX_FMT_RGBA, videoCodecContext->width, videoCodecContext->height, 1); inReturn > 0)&#xA;    {&#xA;        frameBuffer.reserve(inReturn);&#xA;    }&#xA;    else&#xA;    {&#xA;        std::cout &lt;&lt; "Can not get buffer size." &lt;&lt; std::endl;&#xA;        return EXIT_FAILURE;&#xA;    }&#xA;&#xA;    if (const auto inReturn = av_image_fill_arrays(frame->data, frame->linesize, frameBuffer.data(), AV_PIX_FMT_RGBA, videoCodecContext->width, videoCodecContext->height, 1); inReturn &lt; 0)&#xA;    {&#xA;        std::cout &lt;&lt; "Can not fill buffer arrays." &lt;&lt; std::endl;&#xA;        return EXIT_FAILURE;&#xA;    }&#xA;&#xA;    // *** MAIN LOOP *** //&#xA;    while(true)&#xA;    {&#xA;        // Return the next frame of a stream.&#xA;        if(av_read_frame(formatContext, &amp;packet) == 0)&#xA;        {&#xA;            if(packet.stream_index == videoIndex) // Check if it is video packet.&#xA;            {&#xA;                // Send packet to decoder.&#xA;                if(avcodec_send_packet(videoCodecContext, &amp;packet) == 0)&#xA;                {&#xA;                    int returnCode = avcodec_receive_frame(videoCodecContext, decoderFrame); // Get Frame from decoder.&#xA;&#xA;                    if (returnCode == 0) // Transform frame and send it to encoder. And re-stream that.&#xA;                    {&#xA;                        sws_scale(swsContext, decoderFrame->data, decoderFrame->linesize, 0, decoderFrame->height, frame->data, frame->linesize);&#xA;&#xA;                        mat = cv::Mat(videoCodecContext->height, videoCodecContext->width, CV_8UC4, frameBuffer.data(), frame->linesize[0]);&#xA;&#xA;                        cv::resize(mat, mat, cv::Size(1920, 1080), cv::INTER_NEAREST);&#xA;&#xA;                        multimediaProcessing.encode(mat.data, packet.dts, packet.dts, packet.flags == AV_PKT_FLAG_KEY); // Thise line sends cv::Mat to encoder and re-streams it.&#xA;&#xA;                        av_packet_unref(&amp;packet);&#xA;                    }&#xA;                    else if(returnCode == AVERROR(EAGAIN))&#xA;                    {&#xA;                        av_frame_unref(decoderFrame);&#xA;                        av_freep(decoderFrame);&#xA;                    }&#xA;                    else&#xA;                    {&#xA;                        av_frame_unref(decoderFrame);&#xA;                        av_freep(decoderFrame);&#xA;&#xA;                        std::cout &lt;&lt; "Error during decoding." &lt;&lt; std::endl;&#xA;                        return EXIT_FAILURE;&#xA;                    }&#xA;                }&#xA;            }&#xA;            else if(packet.stream_index == audioIndex) // Check if it is audio packet.&#xA;            {&#xA;                std::vector vectorPacket(packet.data, packet.data &#x2B; packet.size);&#xA;&#xA;                multimediaProcessing.addAudioPacket(vectorPacket, packet.dts, packet.dts);&#xA;            }&#xA;            else&#xA;            {&#xA;                av_packet_unref(&amp;packet);&#xA;            }&#xA;        }&#xA;        else&#xA;        {&#xA;            std::cout &lt;&lt; "Can not send video packet to decoder." &lt;&lt; std::endl;&#xA;            std::this_thread::sleep_for(std::chrono::seconds(1));&#xA;        }&#xA;    }&#xA;&#xA;    return EXIT_SUCCESS;&#xA;    }&#xA;</unsigned></string></iostream>

    &#xA;

    What does It do ?

    &#xA;

    It takes a single RTSP stream to decode its data so I can, for example, draw something to its frames or whatever, and then stream it under a different address.

    &#xA;

    Basically, I am opening the RTSP stream, check if it does contain both audio and video streams, and find a decoder for them. Then I create an encoder to which I will tell how the output stream should look like and that's it.

    &#xA;

    And this point I will create an endless loop Where I will read all packets coming from the input stream, then decode it does something to it and again encode it and re=stream it.

    &#xA;

    What is the issue ?

    &#xA;

    If you take a closer look I am sending both video and audio frame together with lastly received PTS and DTS contained in AVPacket, to the encoder.

    &#xA;

    The PTS and DTS from the point when I receive the first AVPacket looks for example like this.

    &#xA;

    IN AUDIO STREAM :

    &#xA;

    &#xA;

    -22783, -21759, -20735, -19711, -18687, -17663, -16639, -15615, -14591, -13567, -12543, -11519, -10495, -9471, -8447, -7423, -6399, -5375, -4351, -3327, -2303, -1279, -255, 769, 1793, 2817, 3841, 4865, 5889, 6913, 7937, 8961, 9985, 11009, 12033, 13057, 14081, 15105, 16129, 17153

    &#xA;

    &#xA;

    As you can see it is every time incremented by 1024 and that is a sample rate of the audio stream. Quite clear here.

    &#xA;

    IN VIDEO STREAM :

    &#xA;

    &#xA;

    86400, 90000, 93600, 97200, 100800, 104400, 108000, 111600, 115200, 118800, 122400, 126000, 129600, 133200, 136800, 140400, 144000, 147600, 151200, 154800, 158400, 162000, 165600

    &#xA;

    &#xA;

    As you can see it is every time incremented by 3600 but WHY ?. What this number actually mean ?

    &#xA;

    From what I can understand, those received PTS and DTS are for the following :

    &#xA;

    DTS should tell the encoder when it should start encoding the frame so the frame in time are in the correct order and not mishmashed.

    &#xA;

    PTS should say the correct time when the frame should be played/displayed in the output stream so the frame in time are in the correct order and not mishmashed.

    &#xA;

    What I am trying to achieve ?

    &#xA;

    As I said I need to restream a RTSP stream. I can not use PTS and DTS which comes from received AVPackets, because at some point it can happen that the input stream can randomly close and I need to open it again. The problem is that when I actually do it, then the PTS and DTS start to generate again from the minus values same as you could see in the samples. I CAN NOT send those "new" PTS and DTS to the encoder because they are now lower than the encoder/muxer expects.

    &#xA;

    I need to continually stream something (both audio and video), even it is a blank black screen or silent audio. And each frame the PTS and DTS should rise by a specific number. I need to figure out how the increment is calculated.

    &#xA;

    ----------------------------------

    &#xA;

    The final result should look like a mosaic of multiple input streams in a single output stream. A single input stream (main) has both audio and video and the rest (side) has just video. Some of those streams can randomly close in time and I need to ensure that it will be back again once it is possible.

    &#xA;

  • ffmpeg scale 4k video and add subtitles

    29 novembre 2020, par goodkid38

    I am having trouble scaling video from 4k to 1080 while still retaining the video sub titles. These subtitles are PGS based and therefore need to be baked into the output video. In order to scale the video I am using ffmpeg with a filter_complex like so :

    &#xA;

    &#x27;-filter_complex&#x27;, `[0:v][0:s:randomSubtitleHere]scale=1920:1080[scaled];[scaled][0:s:0]overlay[v]`, &#xA;&#x27;-map&#x27;, &#x27;[v]&#x27;, &#x27;-map&#x27;, &#xA;`0:a:${movieTitle[&#x27;audioSelect&#x27;]}`,&#xA;

    &#xA;

    This will give me the video at 1080, but it i still am not seeing the subtitles I have selected.

    &#xA;

  • Frame sliced into 2 under some degree. How fix it ?

    26 novembre 2020, par Алекс Аникей

    I trying use h264 codec in videochat application. And in some reason frame sliced into 2 triangle (picture below). I try send my desktop image to another person and get this image on another client.

    &#xA;

    What settings i set wrong ?&#xA;My code :

    &#xA;

    Init :

    &#xA;

    VCSession *vc_new_x264(Logger *log, ToxAV *av, uint32_t friend_number, toxav_video_receive_frame_cb *cb, void *cb_data,&#xA;                       VCSession *vc)&#xA;{&#xA;&#xA;    if (x264_param_default_preset(&amp;param, "slow", "zerolatency") &lt; 0) {&#xA;        // goto fail;&#xA;    }&#xA;&#xA;    param.i_csp = X264_CSP_I420;&#xA;    param.i_width  = 1920;&#xA;    param.i_height = 1080;&#xA;    vc->h264_enc_width = param.i_width;&#xA;    vc->h264_enc_height = param.i_height;&#xA;&#xA;    param.i_keyint_max = 30;&#xA;&#xA;    param.b_vfr_input = 1; /* VFR input.  If 1, use timebase and timestamps for ratecontrol purposes.&#xA;                            * If 0, use fps only. */&#xA;    param.i_timebase_num = 1;       // 1 ms = timebase units = (1/1000)s&#xA;    param.i_timebase_den = 1000;   // 1 ms = timebase units = (1/1000)s&#xA;    param.b_repeat_headers = 1;&#xA;    param.b_annexb = 1;&#xA;&#xA;    param.rc.f_rate_tolerance = VIDEO_F_RATE_TOLERANCE_H264;&#xA;    param.rc.i_vbv_buffer_size = 1500;&#xA;    param.rc.i_vbv_max_bitrate = VIDEO_BITRATE_INITIAL_VALUE_H264 * 1;&#xA;&#xA;    vc->h264_enc_bitrate = VIDEO_BITRATE_INITIAL_VALUE_H264;&#xA;&#xA;    param.rc.i_qp_min = 13;&#xA;    param.rc.i_qp_max = 35; // max quantizer for x264&#xA;&#xA;    vc->h264_enc_bitrate = VIDEO_BITRATE_INITIAL_VALUE_H264;&#xA;&#xA;    param.rc.b_stat_read = 0;&#xA;    param.rc.b_stat_write = 0;&#xA;&#xA;&#xA;    if (x264_param_apply_profile(&amp;param,&#xA;                                 "high") &lt; 0) { // "baseline", "main", "high", "high10", "high422", "high444"&#xA;        // goto fail;&#xA;    }&#xA;&#xA;&#xA;    if (x264_picture_alloc(&amp;(vc->h264_in_pic), param.i_csp, param.i_width, param.i_height) &lt; 0) {&#xA;        // goto fail;&#xA;    }&#xA;&#xA;    vc->h264_encoder = x264_encoder_open(&amp;param);&#xA;&#xA;    AVCodec *codec = NULL;&#xA;    vc->h264_decoder = NULL;&#xA;    avcodec_register_all();&#xA;    codec = NULL;&#xA;&#xA;    codec = avcodec_find_decoder(AV_CODEC_ID_H264);&#xA;&#xA;    if (!codec) {&#xA;        LOGGER_WARNING(log, "codec not found H264 on decoder");&#xA;    }&#xA;&#xA;    vc->h264_decoder = avcodec_alloc_context3(codec);&#xA;&#xA;    if (codec->capabilities &amp; AV_CODEC_CAP_TRUNCATED) {&#xA;        vc->h264_decoder->flags |= AV_CODEC_FLAG_TRUNCATED; /* we do not send complete frames */&#xA;    }&#xA;&#xA;&#xA;    vc->h264_decoder->delay = 5;&#xA;&#xA;    if (avcodec_open2(vc->h264_decoder, codec, NULL) &lt; 0) {&#xA;        LOGGER_WARNING(log, "could not open codec H264 on decoder");&#xA;    }&#xA;&#xA;&#xA;    return vc;&#xA;}&#xA;

    &#xA;

    Get frame and decoding him :

    &#xA;

    void vc_iterate_x264(VCSession *vc)&#xA;{&#xA;&#xA;    if (!vc) {&#xA;        return;&#xA;    }&#xA;&#xA;    pthread_mutex_lock(vc->queue_mutex);&#xA;&#xA;    struct RTPMessage *p;&#xA;&#xA;    if (!rb_read(vc->vbuf_raw, (void **)&amp;p)) {&#xA;        LOGGER_TRACE(vc->log, "no Video frame data available");&#xA;        pthread_mutex_unlock(vc->queue_mutex);&#xA;        return;&#xA;    }&#xA;&#xA;    pthread_mutex_unlock(vc->queue_mutex);&#xA;    const struct RTPHeader *const header = &amp;p->header;&#xA;&#xA;    uint32_t full_data_len;&#xA;&#xA;    if (header->flags &amp; RTP_LARGE_FRAME) {&#xA;        full_data_len = header->data_length_full;&#xA;        LOGGER_WARNING(vc->log, "vc_iterate:001:full_data_len=%d", (int)full_data_len);&#xA;    } else {&#xA;        full_data_len = p->len;&#xA;        if (header->data_length_lower != full_data_len)&#xA;        {&#xA;            LOGGER_ERROR("Data header and packet don&#x27;t equal: %d - header %d - packet", header->data_length_lower, full_data_len);&#xA;        }&#xA;        LOGGER_DEBUG(vc->log, "vc_iterate:002");&#xA;    }&#xA;&#xA;    decode_frame_h264(vc, p, full_data_len);&#xA;}&#xA;&#xA;void decode_frame_h264(VCSession *vc,&#xA;                       struct RTPMessage *p,&#xA;                       uint32_t full_data_len)&#xA;{&#xA;&#xA;    AVPacket *compr_data;&#xA;    compr_data = av_packet_alloc();&#xA;&#xA;&#xA;    uint8_t *tmp_buf = calloc(1, full_data_len &#x2B; FF_INPUT_BUFFER_PADDING_SIZE);&#xA;    memcpy(tmp_buf, p->data, full_data_len);&#xA;&#xA;    compr_data->data = tmp_buf; // p->data;&#xA;    compr_data->size = (int)full_data_len; // hmm, "int" again&#xA;&#xA;    avcodec_send_packet(vc->h264_decoder, compr_data);&#xA;&#xA;    int ret_ = 0;&#xA;    while (ret_ >= 0) {&#xA;        AVFrame *frame = av_frame_alloc();&#xA;        ret_ = avcodec_receive_frame(vc->h264_decoder, frame);&#xA;        if (ret_ == AVERROR(EAGAIN) || ret_ == AVERROR_EOF) {&#xA;            // error&#xA;            break;&#xA;        } else if (ret_ &lt; 0) {&#xA;            // Error during decoding&#xA;            break;&#xA;        } else if (ret_ == 0) {&#xA;            vc->vcb(vc->av, vc->friend_number, frame->width, frame->height,&#xA;                          (const uint8_t *)frame->data[0],&#xA;                          (const uint8_t *)frame->data[1],&#xA;                          (const uint8_t *)frame->data[2],&#xA;                          frame->linesize[0], frame->linesize[1],&#xA;                          frame->linesize[2], vc->vcb_user_data);&#xA;        } else {&#xA;            // some other error&#xA;        }&#xA;        av_frame_free(&amp;frame);&#xA;    }&#xA;    av_packet_free(&amp;compr_data);&#xA;    free(tmp_buf);&#xA;    free(p);&#xA;}&#xA;

    &#xA;

    Send frame and encoding :

    &#xA;

    bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t *y,&#xA;                            const uint8_t *u, const uint8_t *v, Toxav_Err_Send_Frame *error, int16_t kf_max_dist, vpx_codec_er_flags_t error_resilient,&#xA;                            unsigned int my_lag_in_frames, uint16_t kf_mode, uint16_t quality_mode)&#xA;{&#xA;    Toxav_Err_Send_Frame rc = TOXAV_ERR_SEND_FRAME_OK;&#xA;    ToxAVCall *call;&#xA;    uint64_t video_frame_record_timestamp = current_time_monotonic(av->m->mono_time);&#xA;&#xA;    int vpx_encode_flags = 0;&#xA;&#xA;    pthread_mutex_lock(call->mutex_video);&#xA;    pthread_mutex_unlock(av->mutex);&#xA;&#xA;    if (y == nullptr || u == nullptr || v == nullptr) {&#xA;        pthread_mutex_unlock(call->mutex_video);&#xA;        rc = TOXAV_ERR_SEND_FRAME_NULL;&#xA;        goto RETURN;&#xA;    }&#xA;&#xA;&#xA;    if (call->video_rtp->ssrc &lt; VIDEO_SEND_X_KEYFRAMES_FIRST) {&#xA;        // Key frame flag for first frames&#xA;        vpx_encode_flags = VPX_EFLAG_FORCE_KF;&#xA;        LOGGER_INFO(av->m->log, "I_FRAME_FLAG:%d only-i-frame mode", call->video_rtp->ssrc);&#xA;&#xA;        &#x2B;&#x2B;call->video_rtp->ssrc;&#xA;    } else if (call->video_rtp->ssrc == VIDEO_SEND_X_KEYFRAMES_FIRST) {&#xA;        // normal keyframe placement&#xA;        vpx_encode_flags = 0;&#xA;        LOGGER_INFO(av->m->log, "I_FRAME_FLAG:%d normal mode", call->video_rtp->ssrc);&#xA;&#xA;        &#x2B;&#x2B;call->video_rtp->ssrc;&#xA;    }&#xA;&#xA;&#xA;    x264_nal_t *nal = NULL;&#xA;    int i_frame_size = 0;&#xA;&#xA;    uint32_t result = encode_frame_h264(av, friend_number, width, height,&#xA;                                        y, u, v,&#xA;                                        &amp;video_frame_record_timestamp,&#xA;                                        vpx_encode_flags,&#xA;                                        &amp;nal,&#xA;                                        &amp;i_frame_size);&#xA;    if (result != 0) {&#xA;        pthread_mutex_unlock(call->mutex_video);&#xA;        rc = TOXAV_ERR_SEND_FRAME_INVALID;&#xA;        goto RETURN;&#xA;    }&#xA;&#xA;    &#x2B;&#x2B;call->video->frame_counter;&#xA;&#xA;    rc = send_frames_h264(av, friend_number, width, height,&#xA;                          y, u, v, call,&#xA;                          &amp;video_frame_record_timestamp,&#xA;                          vpx_encode_flags,&#xA;                          &amp;nal,&#xA;                          &amp;i_frame_size,&#xA;                          &amp;rc);&#xA;&#xA;    pthread_mutex_unlock(call->mutex_video);&#xA;&#xA;RETURN:&#xA;&#xA;    if (error) {&#xA;        *error = rc;&#xA;    }&#xA;&#xA;    return rc == TOXAV_ERR_SEND_FRAME_OK;&#xA;}&#xA;&#xA;uint32_t send_frames_h264(ToxAV *av, uint32_t friend_number, uint16_t width, uint16_t height,&#xA;                          const uint8_t *y,&#xA;                          const uint8_t *u, const uint8_t *v, ToxAVCall *call,&#xA;                          uint64_t *video_frame_record_timestamp,&#xA;                          int vpx_encode_flags,&#xA;                          x264_nal_t **nal,&#xA;                          int *i_frame_size,&#xA;                          TOXAV_ERR_SEND_FRAME *rc)&#xA;{&#xA;&#xA;    if (*i_frame_size > 0) {&#xA;&#xA;        // use the record timestamp that was actually used for this frame&#xA;        *video_frame_record_timestamp = (uint64_t)call->video->h264_in_pic.i_pts;&#xA;        const uint32_t frame_length_in_bytes = *i_frame_size;&#xA;        const int keyframe = (int)call->video->h264_out_pic.b_keyframe;&#xA;&#xA;        LOGGER_DEBUG(av->m->log, "video packet record time: %lu", (*video_frame_record_timestamp));&#xA;&#xA;        int res = rtp_send_data&#xA;                  (&#xA;                      call->video_rtp,&#xA;                      (const uint8_t *)((*nal)->p_payload),&#xA;                      frame_length_in_bytes,&#xA;                      keyframe,&#xA;                      *video_frame_record_timestamp,&#xA;                      av->m->log&#xA;                  );&#xA;&#xA;        (*video_frame_record_timestamp)&#x2B;&#x2B;;&#xA;&#xA;        if (res &lt; 0) {&#xA;            LOGGER_WARNING(av->m->log, "Could not send video frame: %s", strerror(errno));&#xA;            *rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;&#xA;            return 1;&#xA;        }&#xA;&#xA;        return 0;&#xA;    } else {&#xA;        *rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;&#xA;        return 1;&#xA;    }&#xA;&#xA;}&#xA;

    &#xA;

    I get image like this :

    &#xA;

    enter image description here

    &#xA;