Permalink
Browse files

Fix h.264 frame/keyframe identification in the player.

If a NAL unit that determines a frame start appears as the last NAL
unit in the packet, then the frame start is not identified until the
start of the next packet.  If this new packet has its own NAL unit
that determines a frame start, and that NAL unit is not at the end of
the packet, then only one frame start would be counted rather than
two.  This is fixed by returning the total number of frame starts,
rather than a bool.

In theory, the same problem could exist in the recorder, but it
appears that the packets in the original recording may have some
trailing NAL units that are stripped by the ffmpeg libraries when
assembling the packet for the player, causing the situation not to
occur.
  • Loading branch information...
stichnot authored and jyavenard committed Feb 20, 2013
1 parent d8fa34b commit a5d37fe92059955447df7635a28792b98fe1d612
Showing with 10 additions and 10 deletions.
  1. +9 −9 mythtv/libs/libmythtv/avformatdecoder.cpp
  2. +1 −1 mythtv/libs/libmythtv/avformatdecoder.h
@@ -3073,12 +3073,13 @@ void AvFormatDecoder::MpegPreProcessPkt(AVStream *stream, AVPacket *pkt)
}
}
bool AvFormatDecoder::H264PreProcessPkt(AVStream *stream, AVPacket *pkt)
// Returns the number of frame starts identified in the packet.
int AvFormatDecoder::H264PreProcessPkt(AVStream *stream, AVPacket *pkt)
{
AVCodecContext *context = stream->codec;
const uint8_t *buf = pkt->data;
const uint8_t *buf_end = pkt->data + pkt->size;
bool on_frame = false;
int num_frames = 0;
// crude NAL unit vs Annex B detection.
// the parser only understands Annex B
@@ -3094,7 +3095,7 @@ bool AvFormatDecoder::H264PreProcessPkt(AVStream *stream, AVPacket *pkt)
{
if (pkt->flags & AV_PKT_FLAG_KEY)
HandleGopStart(pkt, false);
return true;
return 1;
}
}
@@ -3107,7 +3108,7 @@ bool AvFormatDecoder::H264PreProcessPkt(AVStream *stream, AVPacket *pkt)
if (m_h264_parser->FieldType() != H264Parser::FIELD_BOTTOM)
{
if (m_h264_parser->onFrameStart())
on_frame = true;
++num_frames;
if (!m_h264_parser->onKeyFrameStart())
continue;
@@ -3207,21 +3208,21 @@ bool AvFormatDecoder::H264PreProcessPkt(AVStream *stream, AVPacket *pkt)
pkt->flags |= AV_PKT_FLAG_KEY;
}
return on_frame;
return num_frames;
}
bool AvFormatDecoder::PreProcessVideoPacket(AVStream *curstream, AVPacket *pkt)
{
AVCodecContext *context = curstream->codec;
bool on_frame = true;
int num_frames = 1;
if (CODEC_IS_FFMPEG_MPEG(context->codec_id))
{
MpegPreProcessPkt(curstream, pkt);
}
else if (CODEC_IS_H264(context->codec_id))
{
on_frame = H264PreProcessPkt(curstream, pkt);
num_frames = H264PreProcessPkt(curstream, pkt);
}
else
{
@@ -3247,8 +3248,7 @@ bool AvFormatDecoder::PreProcessVideoPacket(AVStream *curstream, AVPacket *pkt)
return false;
}
if (on_frame)
framesRead++;
framesRead += num_frames;
if (trackTotalDuration)
totalDuration +=
@@ -220,7 +220,7 @@ class AvFormatDecoder : public DecoderBase
/// Preprocess a packet, setting the video parms if necessary.
void MpegPreProcessPkt(AVStream *stream, AVPacket *pkt);
bool H264PreProcessPkt(AVStream *stream, AVPacket *pkt);
int H264PreProcessPkt(AVStream *stream, AVPacket *pkt);
bool PreProcessVideoPacket(AVStream *stream, AVPacket *pkt);
bool ProcessVideoPacket(AVStream *stream, AVPacket *pkt);
bool ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic);

0 comments on commit a5d37fe

Please sign in to comment.