[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