[Libav-user] Timing timing issues with writing packets
Declan Kelly
dkelly at truevisionsys.com
Mon Jul 6 21:12:51 CEST 2015
Hello,
I've been trying to write part of a larger application that receives frames, then encodes and records them to disk. However, I've been having issue with the timing of the output files. The output files are commonly half of the duration that they should be, almost as if the duration information that I attach the packets isn't having an effect and the packets are being placed immediately one after another. Is there something I'm forgetting in my code? (Write frame function source included below)
Thank you
Source does include some additional scaling and conversion. I've removed extraneous debugging snippets
Source:
TrdMediaWriter::ERROR_CODE TrdMediaWriter::convertAndWrite(const TrdFrame& _frame, double _currTimeInMovie)
{
ERROR_CODE error = ERROR_CODE_NONE;
mWriteMutex.lock();
int avError = 0;
AVPacket packet;
av_init_packet(&packet);
if (packet.pts > 0 && mLastPtsWritten == packet.pts)
{
error = ERROR_WARNING_SAME_PTS;
}
if (error == ERROR_CODE_NONE)
{
////////////////////////////////////////////////////////////////////
double startTime = TrdTimeUtils::getTickTime();
TrdFrame frameToBeWritten = _frame;
if (mWatermark.isReady())
{
TrdFrameUtils::copyFrame(_frame, mWatermarkFrame);
mWatermark.updateFrame(mWatermarkFrame, TrdWatermark::LOCATIONS_LOWER_RIGHT, 10, 10);
frameToBeWritten = mWatermarkFrame;
}
if (mWriteParams.mUseIppConversions)
{
IppiSize size = { 0 };
size.width = frameToBeWritten.getWidth();
size.height = frameToBeWritten.getHeight();
Ipp8u* bufferYUV[3] = { nullptr };
bufferYUV[0] = (Ipp8u*)mFrameYUV;
bufferYUV[1] = (Ipp8u*)(mFrameYUV + (frameToBeWritten.getWidth() * frameToBeWritten.getHeight()));
bufferYUV[2] = (Ipp8u*)(mFrameYUV + (frameToBeWritten.getWidth() * frameToBeWritten.getHeight()) + ((frameToBeWritten.getWidth() * frameToBeWritten.getHeight()) / 4));
/////////////////////////////////////////////////////////////////////////
int pDst[3] = { size.width, size.width / 2, size.width / 2 };
IPPCALL(ippiRGBToYCbCr420_8u_C3P3R) ((Ipp8u*)frameToBeWritten.getFrame(), size.width * 3, bufferYUV, pDst, size);
/////////////////////////////////////////////////////////////////////////
avpicture_fill((AVPicture*)mAVFramePicture, (uint8_t*)mFrameYUV, PIX_FMT_YUV420P, frameToBeWritten.getWidth(), frameToBeWritten.getHeight());
}
else
{
avpicture_fill((AVPicture*)mAVFrameRGB, (uint8_t*)frameToBeWritten.getFrame(), PIX_FMT_RGB24, frameToBeWritten.getWidth(), frameToBeWritten.getHeight());
sws_scale(mSwsConversionContext, mAVFrameRGB->data, mAVFrameRGB->linesize, 0, mAVStream->codec->height, mAVFramePicture->data, mAVFramePicture->linesize);
}
double endTime = TrdTimeUtils::getTickTime();
////////////////////////////////////////////////////////////////////
int got_packet;
packet.data = *mAVFramePicture->data;
packet.size = avpicture_get_size(PIX_FMT_YUV420P, frameToBeWritten.getWidth(), frameToBeWritten.getHeight());
mAVFramePicture->format = PIX_FMT_YUV420P;
mAVFramePicture->height = frameToBeWritten.getHeight();
mAVFramePicture->width = frameToBeWritten.getWidth();
double diffTime = _currTimeInMovie - 0.0;
// Find the frame number for presentation --> diffTime * fps;
int64_t calculatedPts = (unsigned long)((diffTime * (double)mAVStream->time_base.den) / (double)mAVStream->time_base.num);
int enc_error = avcodec_encode_video2(mAVStream->codec, &packet, mAVFramePicture, &got_packet);
if (enc_error >= 0 && got_packet != 0)
{
if (mAVStream->codec->coded_frame->key_frame)
{
packet.flags |= AV_PKT_FLAG_KEY;
}
packet.stream_index = mAVStream->index;
packet.pts = calculatedPts;
av_packet_rescale_ts(&packet, mAVStream->codec->time_base, mAVStream->time_base);
packet.duration = ((diffTime - mLastTimeWritten) * (double)mAVStream->time_base.den) / ((double)mAVStream->time_base.num);
mLastPtsWritten = packet.pts;
mLastTimeWritten = _currTimeInMovie;
avError = av_interleaved_write_frame(mAVFormatContext, &packet);
mRecordLogFrameCount++;
if (avError != 0)
{
error = ERROR_CODES_FILE_WRITE_FAILED;
}
} // end of -- if (bytesToWrite > 0)
else
{
error = ERROR_CODES_ENCODING_FAILED;
}
} // end of -- if (error == ERROR_CODE_NONE)
av_free_packet(&packet);
mWriteMutex.unlock();
return (error);
} // end of -- ERROR_CODE TrdMediaWriter::convertAndWrite(const TrdFrame& _frame, double _beginTime, double _currTimeInMovie)
More information about the Libav-user
mailing list