Dmi*_*rov 3 c++ ffmpeg rtp h.264
我正在使用live555和ffmpeg库从服务器获取和解码RTP H264流; 视频流由ffmpeg编码,使用Baseline profile和
x264_param_default_preset(m_params, "veryfast", "zerolatency")
Run Code Online (Sandbox Code Playgroud)
我阅读了这个主题并在每帧中添加了SPS和PPS数据,这是我从网络收到的;
void ClientSink::NewFrameHandler(unsigned frameSize, unsigned numTruncatedBytes,
timeval presentationTime, unsigned durationInMicroseconds)
{
...
EncodedFrame tmp;
tmp.m_frame = std::vector<unsigned char>(m_tempBuffer.data(), m_tempBuffer.data() + frameSize);
tmp.m_duration = durationInMicroseconds;
tmp.m_pts = presentationTime;
//Add SPS and PPS data into the frame; TODO: some devices may send SPS and PPs data already into frame;
tmp.m_frame.insert(tmp.m_frame.begin(), m_spsPpsData.cbegin(), m_spsPpsData.cend());
emit newEncodedFrame( SharedEncodedFrame(tmp) );
m_frameCounter++;
this->continuePlaying();
}
Run Code Online (Sandbox Code Playgroud)
我在解码器中收到这些帧.
bool H264Decoder::decodeFrame(SharedEncodedFrame orig_frame)
{
...
while(m_packet.size > 0)
{
int got_picture;
int len = avcodec_decode_video2(m_decoderContext, m_picture, &got_picture, &m_packet);
if (len < 0)
{
emit criticalError(QString("Decoding error"));
return false;
}
if (got_picture)
{
std::vector<unsigned char> result;
this->storePicture(result);
if ( m_picture->format == AVPixelFormat::AV_PIX_FMT_YUV420P )
{
//QImage img = QImage(result.data(), m_picture->width, m_picture->height, QImage::Format_RGB888);
Frame_t result_rgb;
if (!convert_yuv420p_to_rgb32(result, m_picture->width, m_picture->height, result_rgb))
{
emit criticalError( QString("Failed to convert YUV420p image into rgb32; can't create QImage!"));
return false;
}
unsigned char* copy_img = new unsigned char[result_rgb.size()];
//this needed because QImage shared buffer, which used, and it will crash, if i use this qimage after result_rgb deleting
std::copy(result_rgb.cbegin(), result_rgb.cend(), copy_img);
QImage img = QImage(copy_img, m_picture->width, m_picture->height, QImage::Format_RGB32,
[](void* array)
{
delete[] array;
}, copy_img);
img.save(QString("123.bmp"));
emit newDecodedFrame(img);
}
Run Code Online (Sandbox Code Playgroud)
avcodec_decode_video2解码没有任何错误消息的帧,但解码后的帧(从yuv420p转换为rgb32)无效.此链接上提供的图像示例
你有什么想法我错了吗?
我怀疑错误是在convert_yuv420p_to_rgb32()代码中.试试这个:
static SwsContext *m_swsCtx = NULL;
QImage frame = QImage ( m_picture->width, m_picture->height,
QImage::Format_RGB32 );
m_swsCtx = sws_getCachedContext ( m_swsCtx, m_picture->width,
m_picture->height, PIX_FMT_YUV420P,
m_picture->width, m_picture->height,
AV_PIX_FMT_RGB32, SWS_BICUBIC,
NULL, NULL, NULL );
uint8_t *dstSlice[] = { frame.bits() };
int dstStride = frame.width() * 4;
sws_scale ( m_swsCtx, &m_picture.data, &m_picture.linesize,
0, m_picture->height, dstSlice, &dstStride );
Run Code Online (Sandbox Code Playgroud)
如果尚未包含/链接swscale,则需要包含/链接swscale.
注意:每帧都不需要SPS/PPS(在关键帧上足够好).但它也没有伤害.