Поврежденный кадр FFMPEG при потоковой передаче в UDP (MPEGTS)

avatar
user37616
8 апреля 2018 в 08:03
1752
1
0

Я работаю над программой потоковой передачи экрана, до сих пор я могу отлично захватывать и кодировать свой экран в видео. Однако всякий раз, когда я пытаюсь передать его через локальную сеть и воспроизвести с помощью Mplayer, он может работать на простом рабочем столе (текстовый документ и т. д.), но когда я пытаюсь воспроизвести видео, кадр, указанный как поврежденный, пока я не выйду из видео (это видео вызывает самый поврежденный кадр https://www.youtube.com/watch?v=1La4QzGeaaQ&t=230s)

Я не совсем понимаю, почему при потоковой передаче я получил поврежденный кадр с видео на YouTube, но при сохранении его в файл (измените URL-адрес с udp://192.168.1.xxx:YYYY на имя файла C:\Test. ts) поврежденных фреймов не было вообще. Мой журнал Mplayer:

`V:   0.0 1563/1563 51% 43%  0.0% 0 0
[h264 @ 0000000001d04940]Invalid NAL unit 0, skipping.
[h264 @ 0000000001d04940]error while decoding MB 23 51, bytestream -64
[h264 @ 0000000001d04940]concealing 2066 DC, 2066 AC, 2066 MV errors in I frame
V:   0.0 1564/1564 51% 43%  0.0% 0 0
[h264 @ 0000000001d04940]concealing 7598 DC, 7598 AC, 7598 MV errors in P frame
V:   0.0 1652/1652 50% 43%  0.0% 0 0
[h264 @ 0000000001d04940]Invalid NAL unit 0, skipping.
[h264 @ 0000000001d04940]error while decoding MB 26 49, bytestream -55
[h264 @ 0000000001d04940]concealing 2303 DC, 2303 AC, 2303 MV errors in I frame
V:   0.0 1653/1653 50% 43%  0.0% 0 0
[h264 @ 0000000001d04940]concealing 7727 DC, 7727 AC, 7727 MV errors in P frame
V:   0.0 1741/1741 49% 43%  0.0% 0 0
[h264 @ 0000000001d04940]Invalid NAL unit 0, skipping.
[h264 @ 0000000001d04940]error while decoding MB 65 62, bytestream -57
[h264 @ 0000000001d04940]concealing 704 DC, 704 AC, 704 MV errors in I frame
V:   0.0 1742/1742 49% 43%  0.0% 0 0`

Код инициализации потока

static void Stream_ini(const char *Url, AVFormatContext *&ofmt_ctx, AVCodec *codec, AVCodecContext *c, AVStream *&out_stream)
{
    int ret;


    avformat_alloc_output_context2(&ofmt_ctx, NULL, "mpegts", Url);
    out_stream = avformat_new_stream(ofmt_ctx, codec)
    out_stream->codec = c;
    av_dump_format(ofmt_ctx, 0, Url, 1);


    if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
        out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
    if (!(ofmt_ctx->flags & AVFMT_NOFILE))
    {
        ret = avio_open(&ofmt_ctx->pb, Url, AVIO_FLAG_WRITE);
        if (ret < 0)
        {
            printf("Could not open output URL '%s'", Url);
            return;
        }
    }


    ret = avformat_write_header(ofmt_ctx, NULL);

    if (ret < 0)
    {
        printf("Error occurred when opening output URL\n");
        return;
    }


}

этот код получит захваченный экран и отправит его кодировщику:

ScreenCap.load_screen_data(inFrame,timmer)  // this will capture screen and return the time and AVFrame for encoding
sws_scale(ctx, inFrame->data, inFrame->linesize, 0,c->height, frame->data, frame->linesize);

frame->pts = (timmer - first_frame_time) / fps;
EncodeToPkT(c, frame, pkt, ofmt_ctx,out_stream);

av_frame_free(&inFrame);

Затем AVFrame будет отправлен кодировщику с использованием avcodec_send_frame() для получения пакетных данных и av_interleaved_write_frame() для потоковой передачи по локальной сети.

Все проверки ошибок удалены для простоты

Кроме того, это моя настройка AVCodecContex для кодировщика:

c->bit_rate = 15000000;
c->width = 1920;
c->height = 1080;
c->time_base = AVRational{ 1, 90 };
c->framerate = AVRational{ 90, 1 };
c->gop_size = 90;
c->max_b_frames = 0;
c->pix_fmt = AV_PIX_FMT_RGB0;

Я также заметил, что это происходит только тогда, когда я увеличиваю битрейт кодировщика (15 МБит), но когда я уменьшаю его до (10 МБИТ), это происходит меньше. А при уменьшении до 2 МБит испорченного кадра больше не происходит, однако качество действительно плохое.
Я тестирую потоковую передачу в локальной сети, используя: ПК -> кабель -> ноутбук, ПК -> беспроводная связь -> ноутбук, ПК -> виртуальный ПК, только ПК (введите IP-адрес ПК как в программе, так и в Mplayer), все получили тот же результат.

Я также тестирую свою функцию DXGICap.load_screen_data, заставляя ее выводить необработанное изображение, и не было никакого поврежденного изображения

Кто-нибудь знает почему.

Спасибо, Нам.

Источник

Ответы (1)

avatar
T. Pihl
9 апреля 2018 в 09:09
2

Это не просто случай использования UDP, т.е. вы будете получать пакеты не по порядку, а декодирование будет давать сбой/жаловаться? Попробуйте использовать TCP и посмотрите, что произойдет.