FFmpeg流解码-不使用ffplay时出现伪像

8
我使用libx264通过RTP流传输视频。目前,我只是将视频流传输到本地主机。 我使用ffmpeg库观看流。当我将GOP大小设置为大于1(仅I帧)时,接收方会出现伪影received image。奇怪的是,当我使用ffplay时,图像是完美的like original。我做错了什么?

编码设置

output_codec_ctx->bit_rate = 5000000;
output_codec_ctx->width = 1920;
output_codec_ctx->height = 1080;
output_codec_ctx->time_base.den = 30; // frames per second
output_codec_ctx->time_base.num = 1;
output_codec_ctx->gop_size = 10; // gop size
output_codec_ctx->max_b_frames = 0; // B frames
output_codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P; // output pixel format
output_codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO;

av_opt_set(output_codec_ctx->priv_data, "preset", "ultrafast", 0);
av_opt_set(output_codec_ctx->priv_data, "tune", "zerolatency", 0);

解码的代码

AVFormatContext *pFormatCtx;
AVCodecContext *input_codec_ctx;
AVCode *pCodec;
avdevice_register_all(); // for device
avformat_network_init();
pFormatCtx = avformat_alloc_context();
input_codec_ctx = avcodec_alloc_context3(nullptr);
AVDictionary *options = nullptr;
av_dict_set(&options, "protocol_whitelist", "file,udp,rtp", 0);
av_dict_set(&options, "fflags", "nobuffer",0);

avformat_open_input(&pFormatCtx, "rtp://127.0.0.1:49990", nullptr, &options);

avformat_find_stream_info(pFormatCtx, nullptr);
for (uint i = 0; i < pFormatCtx->nb_streams; i++)
 {
   if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
   {
     videoStream = static_cast<int>(i);
     break;
   }

 }

av_read_play(pFormatCtx);    //play stream
pCodec = avcodec_find_decoder(pFormatCtx->streams[videoStream]->codecpar->codec_id);
AVCodecParameters *codec_param = pFormatCtx->streams[videoStream]->codecpar;
avcodec_parameters_to_context(input_codec_ctx, codec_param);
avcodec_open2(input_codec_ctx, pCodec, nullptr);

AVPacket packet;
AVPacket *pkt  = &packet;
AVFrame *frame;
frame = av_frame_alloc();

av_init_packet(pkt);
pkt->data = nullptr;    // packet data will be allocated by the encoder
pkt->size = 0;

while(true){
    av_read_frame(pFormatCtx,pkt);
    avcodec_send_packet(input_codec_ctx,pkt);
    avcodec_receive_frame(input_codec_ctx,frame);
}

省略了初始化和其他操作。自定义解码的控制台输出:

NULL @ 0x1fb7b80] Opening 'stream.sdp' for reading
[sdp @ 0x1fb7b80] Format sdp probed with size=2048 and score=50
[sdp @ 0x1fb7b80] video codec set to: h264
[sdp @ 0x1fb7b80] RTP Packetization Mode: 1
[udp @ 0x1f34140] end receive buffer size reported is 131072
[udp @ 0x1fb8e40] end receive buffer size reported is 131072
[sdp @ 0x1fb7b80] setting jitter buffer size to 500

 Success !
[sdp @ 0x1fb7b80] Before avformat_find_stream_info() pos: 181 bytes read:181 seeks:0 nb_streams:1
[AVBSFContext @ 0x1fa5880] nal_unit_type: 7(SPS), nal_ref_idc: 3
[AVBSFContext @ 0x1fa5880] nal_unit_type: 8(PPS), nal_ref_idc: 3
[AVBSFContext @ 0x1fa5880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[AVBSFContext @ 0x1fa5880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[AVBSFContext @ 0x1fa5880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[AVBSFContext @ 0x1fa5880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[AVBSFContext @ 0x1fa5880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[AVBSFContext @ 0x1fa5880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[AVBSFContext @ 0x1fa5880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[AVBSFContext @ 0x1fa5880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] Format yuv420p chosen by get_format().
[h264 @ 0x1fa51c0] Reinit context to 1920x1088, pix_fmt: yuv420p
[sdp @ 0x1fb7b80] max delay reached. need to consume packet
[sdp @ 0x1fb7b80] RTP: missed 57 packets
[h264 @ 0x1fa51c0] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] Invalid level prefix
[h264 @ 0x1fa51c0] error while decoding MB 2 36
[h264 @ 0x1fa51c0] concealing 3887 DC, 3887 AC, 3887 MV errors in I frame
[h264 @ 0x1fa51c0] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[sdp @ 0x1fb7b80] max delay reached. need to consume packet
[sdp @ 0x1fb7b80] RTP: missed 155 packets
[h264 @ 0x1fa51c0] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] corrupted macroblock 32 41 (total_coeff=-1)
[h264 @ 0x1fa51c0] error while decoding MB 32 41
[h264 @ 0x1fa51c0] concealing 3257 DC, 3257 AC, 3257 MV errors in I frame
[h264 @ 0x1fa51c0] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1fa51c0] nal_unit_type: 5(IDR), nal_ref_idc: 3
[sdp @ 0x1fb7b80] max delay reached. need to consume packet
[sdp @ 0x1fb7b80] RTP: missed 52 packets
[sdp @ 0x1fb7b80] max delay reached. need to consume packet
[sdp @ 0x1fb7b80] RTP: missed 51 packets
[sdp @ 0x1fb7b80] max delay reached. need to consume packet
[sdp @ 0x1fb7b80] RTP: missed 10 packets
[sdp @ 0x1fb7b80] max delay reached. need to consume packet
[sdp @ 0x1fb7b80] RTP: missed 50 packets
[sdp @ 0x1fb7b80] max delay reached. need to consume packet
[sdp @ 0x1fb7b80] RTP: missed 52 packets
[sdp @ 0x1fb7b80] All info found
[sdp @ 0x1fb7b80] After avformat_find_stream_info() pos: 181 bytes read:181 seeks:0 frames:28
found video stream 

The number of elements in stream is  1 

[h264 @ 0x1ee3880] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] Format yuv420p chosen by get_format().
[h264 @ 0x1ee3880] Reinit context to 1920x1088, pix_fmt: yuv420p
[h264 @ 0x1ee3880] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[sdp @ 0x1fb7b80] max delay reached. need to consume packet
[sdp @ 0x1fb7b80] RTP: missed 256 packets
[h264 @ 0x1ee3880] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] Invalid level prefix
[h264 @ 0x1ee3880] error while decoding MB 119 41
[h264 @ 0x1ee3880] concealing 3170 DC, 3170 AC, 3170 MV errors in I frame
[h264 @ 0x1ee3880] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[sdp @ 0x1fb7b80] max delay reached. need to consume packet
[sdp @ 0x1fb7b80] RTP: missed 5 packets
[sdp @ 0x1fb7b80] max delay reached. need to consume packet
[sdp @ 0x1fb7b80] RTP: missed 4 packets
[h264 @ 0x1ee3880] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] out of range intra chroma pred mode
[h264 @ 0x1ee3880] error while decoding MB 100 56
[h264 @ 0x1ee3880] corrupted macroblock 84 65 (total_coeff=-1)
[h264 @ 0x1ee3880] error while decoding MB 84 65
[h264 @ 0x1ee3880] concealing 754 DC, 754 AC, 754 MV errors in I frame
[sdp @ 0x1fb7b80] max delay reached. need to consume packet
[sdp @ 0x1fb7b80] RTP: missed 160 packets
[h264 @ 0x1ee3880] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] corrupted macroblock 17 36 (total_coeff=-1)
[h264 @ 0x1ee3880] error while decoding MB 17 36
[h264 @ 0x1ee3880] concealing 3872 DC, 3872 AC, 3872 MV errors in I frame
[h264 @ 0x1ee3880] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[sdp @ 0x1fb7b80] max delay reached. need to consume packet
[sdp @ 0x1fb7b80] RTP: missed 53 packets
[h264 @ 0x1ee3880] nal_unit_type: 7(SPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 8(PPS), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] nal_unit_type: 5(IDR), nal_ref_idc: 3
[h264 @ 0x1ee3880] corrupted macroblock 62 39 (total_coeff=-1)
[h264 @ 0x1ee3880] error while decoding MB 62 39
[h264 @ 0x1ee3880] concealing 3467 DC, 3467 AC, 3467 MV errors in I frame

尝试使用GOP = 14和可能的max_b_frames = 2。 - Ripi2
@Ripi2 不会改变任何东西。 - Lucker10
可能与https://superuser.com/questions/1349925/artifact-while-streaming-multicast-with-ffmpeg?newreg=b9c43a92c5f94a008e14b1235e65e1f3有关。 - Lucker10
1个回答

7
最终我通过实现与ffplay相同的方式解决了它:一个线程执行av_read_frame()并将接收到的数据包推送到packetqueue中,第二个线程对数据包进行解码。
不知道为什么单线程不起作用。
您可以从以下代码片段中获取一个示例:
PacketReceiver:
must_abort = false; // class member, externally set to true if abort requested
AVPacket packet;
AVPacket *pkt  = &packet;
int ret;

while (must_abort == false){
    ret = av_read_frame(pFormatCtx,pkt);
    if (ret>=0 && !must_abort){
        queue->putPacket(pkt);
    }
    else{
        qDebug("no packet received");
    }
    QApplication::processEvents();
}

数据包队列:

class PacketQueue{
public:
void init(){
    abort_request = false;
}
void putPacket(AVPacket *pkt) {

    mutex.lock();
    queue.enqueue(*pkt);
    waitForNewPacket.wakeAll();
    mutex.unlock();
}

int getPacket(AVPacket *pkt){
    int ret;
    mutex.lock();
    forever {
        if (abort_request) {
            ret = -1;
            break;
        }
        if (queue.size() == 0){
            if (waitForNewPacket.wait(&mutex, 1000)){
            }else{
                qDebug("PacketQueue timeout, try again...");
            }
            continue;
        }
        *pkt= queue.dequeue();
        ret = 1;
        break;
    }

    mutex.unlock();
    return ret;
}

void abort(){
    mutex.lock();
    abort_request = true;
    mutex.unlock();
}

bool abort_request;
QQueue<AVPacket> queue;
QMutex mutex;
QWaitCondition waitForNewPacket;
};

解码器:

AVFrame *frame = av_frame_alloc();
AVFrame *frame_RGB = av_frame_alloc();
struct SwsContext *img_convert_ctx = nullptr;
int ret;
int cnt = 0;
int width_current = 0;
int height_current = 0;

avcodec_flush_buffers(mData->input_codec_ctx);

forever{
    cnt++;
    ret = decodeFrame(frame);
    if (ret < 0 ){
        break;
    }
    if (ret == 0){
        continue;
    }

    // check if height and width have changed
    if (width_current != frame->width || height_current != frame->height){
        av_frame_free(&frame_RGB);
        frame_RGB = av_frame_alloc();
        frame_RGB->width = width_current = frame->width;
        frame_RGB->height = height_current = frame->height;
        frame_RGB->format = AV_PIX_FMT_RGB24;
        av_image_alloc(frame_RGB->data, frame_RGB->linesize, frame_RGB->width, frame_RGB->height, AV_PIX_FMT_RGB24, 32);
        img_convert_ctx = sws_getContext(   frame->width,
                                            frame->height,
                                            static_cast<AVPixelFormat>(frame->format),
                                            frame->width,
                                            frame->height,
                                            AV_PIX_FMT_RGB24,
                                            SWS_BICUBIC,
                                            nullptr, nullptr, nullptr);
    }

    if (img_convert_ctx != nullptr) {
        sws_scale(img_convert_ctx, static_cast<uint8_t const * const  *>(frame->data),
                  frame->linesize, 0, frame->height,
                  frame_RGB->data, frame_RGB->linesize);
        // here is the frame available as RGB in frame_RGB
    }

    av_frame_unref(frame);

}

}

int VideoDecoder::decodeFrame(AVFrame* frame){
int ret = AVERROR(EAGAIN);

forever {
    AVPacket pkt;

    do {
        ret = avcodec_receive_frame(input_codec_ctx, frame);
        if (ret >= 0) {
            //frame->pts = frame->pkt_dts;
            //frame->pts = frame->best_effort_timestamp;
        }

        if (ret == AVERROR_EOF) {
            avcodec_flush_buffers(input_codec_ctx);
            return 0;
        }
        if (ret >= 0)
            return 1;
    } while (ret != AVERROR(EAGAIN));

    if (queue->getPacket(&pkt) < 0)
        return -1;        

    ret = avcodec_send_packet(input_codec_ctx, &pkt);

    if (ret == AVERROR(EAGAIN)) {
        qFatal("Receive_frame and send_packet both returned EAGAIN, which is an API violation.");
    }

    if (pkt.buf->buffer != nullptr){
        av_packet_unref(&pkt);
    }else{
        qDebug() << "Packet cannot be freed, pkt.buf->buffer == NULL!";
    }

}
}

关于你的解决方案,我有一些快速的注释:你正在将相同的AVPacket推送到队列中(因为通过指针传递相同的实例)。相反,在流读取器中应该为每个新数据包分配av_packet_alloc,并在解码器中释放每个数据包,以避免这种情况。 - ElDorado
那是故意的。我想节省分配和释放所需的时间...也许不是最佳实践,但对于更大的比特率应该会更快。 - Lucker10
我遇到了同样的问题,多线程的方法完美地解决了它。回想起来,这似乎很明显,但在一个线程中完成所有这些工作可能会阻塞帧解码接收数据包。一旦我将这些过程分成多个线程,所有数据包丢失都消失了,并且出乎意料的是,整体CPU利用率也大大降低了。 - rumdrums

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接