我使用ffmpeg确实读取了udp流(仅包含视频)并解码了帧,然后我又想再次编码,但是在解码或从解复用过程中,我得到的是模糊的图片,尤其是下部。
我有一个视频播放器,它也使用ffmpeg来完美显示视频,我尝试查看该代码,但看不到任何差异。
在日志中,我认为
Invalid NAL unit 8, skipping. nal_unit_type: 1(Coded slice of a non-IDR picture), nal_ref_idc: 3 Invalid NAL unit 7, skipping. bytestream overread td error while decoding MB 109 49, bytestream td
代码中的主要内容如下:
av_register_all();
AVFormatContext *fmt_ctx = 0;
AVDictionary *options = 0;
av_dict_set(&options, "analyzeduration", "500000", NULL);
av_dict_set(&options, "probesize", "500000", NULL);
char* url = "udp://239.0.0.3:8081";
avformat_open_input(&fmt_ctx, url, 0, &options);
avformat_find_stream_info(fmt_ctx, &options);
int nRet = 0;
av_dump_format(fmt_ctx, 0, url, 0);
AVStream *pStream = fmt_ctx->streams[0];
AVCodecID nCodecid = pStream->codec->codec_id;
AVCodec* pCodec = avcodec_find_decoder(nCodecid);
AVCodecContext* pCodecCtx = pStream->codec;
nRet = avcodec_open2(pCodecCtx, pCodec, NULL);
int nInH = pStream->codec->height;
int nInW = pStream->codec->width;
int nOutW = nInW / 4;
int nOutH = nInH / 4;
SwsContext* pSwsCtx = sws_getContext(nInW, nInH, AV_PIX_FMT_YUV420P,
nOutW, nOutH, AV_PIX_FMT_RGB24,
SWS_BICUBIC, NULL, NULL, NULL);
m_pFilmWdg->m_img = QImage(nOutW, nOutH, QImage::Format_RGB888);
int linesizes[4];
av_image_fill_linesizes(linesizes, AV_PIX_FMT_RGB24, nOutW);
for (;;)
{
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
nRet = av_read_frame(fmt_ctx, &pkt);
nRet = avcodec_send_packet(pCodecCtx, &pkt);
AVFrame* picture = av_frame_alloc();
nRet = avcodec_receive_frame(pCodecCtx, picture);
if (AVERROR(EAGAIN) == nRet)
continue;
uint8_t* p[] = { m_pFilmWdg->m_img.bits() };
nRet = sws_scale(pSwsCtx, picture->data, picture->linesize, 0, nInH, p, linesizes);
av_packet_unref(&pkt);
av_frame_free(&picture);
m_pFilmWdg->update();
}
答案 0 :(得分:0)
经过大量调试,我发现了问题所在。问题是udp软件包在解码期间丢失或损坏。我将循环分成两个不同的线程。一 DemuxLoop和一个DecodeLoop之类的
void VideoDecode::DemuxLoop()
{
..
int nRet = av_read_frame(fmt_ctx, &pkt);
put in queue
}
void VideoDecode::DecodeLoop()
{
...
pick from queue
int nRet = avcodec_send_packet(pCodecCtx, &pkt);
AVFrame* picture = av_frame_alloc();
nRet = avcodec_receive_frame(pCodecCtx, picture);
...
}