Skip to content

Commit

Permalink
Merge pull request HandBrake#330 from Rodeo314/hbft
Browse files Browse the repository at this point in the history
libhb: rework keyframe handling.
  • Loading branch information
twalker314 authored Sep 18, 2016
2 parents c18bbea + 38a566b commit a8b4a5a
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 96 deletions.
16 changes: 11 additions & 5 deletions libhb/decavcodec.c
Original file line number Diff line number Diff line change
Expand Up @@ -957,16 +957,22 @@ static hb_buffer_t * cc_fill_buffer(hb_work_private_t *pv, uint8_t *cc, int size

static int get_frame_type(int type)
{
switch(type)
switch (type)
{
case AV_PICTURE_TYPE_I:
return HB_FRAME_I;
case AV_PICTURE_TYPE_B:
return HB_FRAME_B;

case AV_PICTURE_TYPE_S:
case AV_PICTURE_TYPE_P:
case AV_PICTURE_TYPE_SP:
return HB_FRAME_P;

case AV_PICTURE_TYPE_BI:
case AV_PICTURE_TYPE_SI:
case AV_PICTURE_TYPE_I:
default:
return HB_FRAME_I;
}
return 0;
}

/*
Expand Down Expand Up @@ -1008,7 +1014,7 @@ static int decodeFrame( hb_work_object_t *w, packet_info_t * packet_info )
// libav avcodec_decode_video2() needs AVPacket flagged with
// AV_PKT_FLAG_KEY for some codecs. For example, sequence of
// PNG in a mov container.
if (packet_info->frametype & HB_FRAME_KEY)
if (packet_info->frametype & HB_FRAME_MASK_KEY)
{
avp.flags |= AV_PKT_FLAG_KEY;
}
Expand Down
24 changes: 17 additions & 7 deletions libhb/enc_qsv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1595,12 +1595,6 @@ static void compute_init_delay(hb_work_private_t *pv, mfxBitstream *bs)
pv->init_delay = NULL;
}

static int qsv_frame_is_key(mfxU16 FrameType)
{
return ((FrameType & MFX_FRAMETYPE_IDR) ||
(FrameType == MFX_FRAMETYPE_UNKNOWN));
}

static void qsv_bitstream_slurp(hb_work_private_t *pv, mfxBitstream *bs)
{
hb_buffer_t *buf;
Expand Down Expand Up @@ -1633,6 +1627,22 @@ static void qsv_bitstream_slurp(hb_work_private_t *pv, mfxBitstream *bs)
bs->MaxLength = pv->job->qsv.ctx->enc_space->p_buf_max_size;

buf->s.frametype = hb_qsv_frametype_xlat(bs->FrameType, &buf->s.flags);
if (pv->param.videoParam->mfx.CodecId == MFX_CODEC_HEVC)
{
size_t len = buf->size;
uint8_t *pos = buf->data;
uint8_t *end = pos + len;
while ((pos = hb_annexb_find_next_nalu(pos, &len)) != NULL)
{
if (HB_HEVC_NALU_KEYFRAME((pos[0] >> 1) & 0x3f))
{
buf->s.flags |= HB_FLAG_FRAMETYPE_KEY;
break;
}
len = end - pos;
continue;
}
}
buf->s.start = buf->s.renderOffset = bs->TimeStamp;
buf->s.stop = buf->s.start + get_frame_duration(pv, buf);
buf->s.duration = buf->s.stop - buf->s.start;
Expand Down Expand Up @@ -1686,7 +1696,7 @@ static void qsv_bitstream_slurp(hb_work_private_t *pv, mfxBitstream *bs)
* If we have a chapter marker pending and this frame's PTS
* is at or after the marker's PTS, use it as the chapter start.
*/
if (qsv_frame_is_key(bs->FrameType))
if (buf->s.flags & HB_FLAG_FRAMETYPE_KEY)
{
hb_chapter_dequeue(pv->chapter_queue, buf);
}
Expand Down
53 changes: 15 additions & 38 deletions libhb/encavcodec.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,58 +443,36 @@ static void compute_dts_offset( hb_work_private_t * pv, hb_buffer_t * buf )

static uint8_t convert_pict_type( int pict_type, char pkt_flag_key, uint16_t* sflags )
{
uint16_t flags = 0;
uint8_t retval = 0;
switch ( pict_type )
switch (pict_type)
{
case AV_PICTURE_TYPE_P:
{
retval = HB_FRAME_P;
} break;

case AV_PICTURE_TYPE_B:
{
retval = HB_FRAME_B;
} break;
break;

case AV_PICTURE_TYPE_S:
{
retval = HB_FRAME_P;
} break;

case AV_PICTURE_TYPE_P:
case AV_PICTURE_TYPE_SP:
{
retval = HB_FRAME_P;
} break;
break;


case AV_PICTURE_TYPE_BI:
case AV_PICTURE_TYPE_SI:
case AV_PICTURE_TYPE_I:
{
*sflags |= HB_FRAME_REF;
if ( pkt_flag_key )
{
retval = HB_FRAME_IDR;
}
else
{
retval = HB_FRAME_I;
}
} break;

default:
{
if ( pkt_flag_key )
{
//buf->s.flags |= HB_FRAME_REF;
*sflags |= HB_FRAME_REF;
retval = HB_FRAME_KEY;
}
else
{
retval = HB_FRAME_REF;
}
flags |= HB_FLAG_FRAMETYPE_REF;
retval = HB_FRAME_I;
} break;
}
if (pkt_flag_key)
{
flags |= HB_FLAG_FRAMETYPE_REF;
flags |= HB_FLAG_FRAMETYPE_KEY;
}
*sflags = flags;
return retval;
}

Expand Down Expand Up @@ -639,9 +617,8 @@ int encavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
buf->s.start = get_frame_start( pv, frameno );
buf->s.duration = get_frame_duration( pv, frameno );
buf->s.stop = buf->s.stop + buf->s.duration;
buf->s.flags &= ~HB_FRAME_REF;
buf->s.frametype = convert_pict_type( pv->context->coded_frame->pict_type, pkt.flags & AV_PKT_FLAG_KEY, &buf->s.flags );
if (buf->s.frametype & HB_FRAME_KEY)
if (buf->s.flags & HB_FLAG_FRAMETYPE_KEY)
{
hb_chapter_dequeue(pv->chapter_queue, buf);
}
Expand Down
7 changes: 6 additions & 1 deletion libhb/enctheora.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,12 @@ int enctheoraWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
buf->f.fmt = AV_PIX_FMT_YUV420P;
buf->f.width = frame_width;
buf->f.height = frame_height;
buf->s.frametype = ( th_packet_iskeyframe(&op) ) ? HB_FRAME_KEY : HB_FRAME_REF;
buf->s.flags = HB_FLAG_FRAMETYPE_REF;
buf->s.frametype = HB_FRAME_I;
if (th_packet_iskeyframe(&op))
{
buf->s.flags |= HB_FLAG_FRAMETYPE_KEY;
}
buf->s.start = in->s.start;
buf->s.stop = in->s.stop;
buf->s.duration = in->s.stop - in->s.start;
Expand Down
49 changes: 24 additions & 25 deletions libhb/encx264.c
Original file line number Diff line number Diff line change
Expand Up @@ -652,15 +652,11 @@ static hb_buffer_t *nal_encode( hb_work_object_t *w, x264_picture_t *pic_out,
w->config->h264.init_delay = -pic_out->i_dts;
}

/* Decide what type of frame we have. */
switch( pic_out->i_type )
/* Determine what type of frame we have. */
switch (pic_out->i_type)
{
case X264_TYPE_IDR:
// Handled in b_keyframe check below.
break;

case X264_TYPE_I:
buf->s.frametype = HB_FRAME_I;
buf->s.frametype = HB_FRAME_IDR;
break;

case X264_TYPE_P:
Expand All @@ -671,24 +667,20 @@ static hb_buffer_t *nal_encode( hb_work_object_t *w, x264_picture_t *pic_out,
buf->s.frametype = HB_FRAME_B;
break;

/* This is for b-pyramid, which has reference b-frames
However, it doesn't seem to ever be used... */
case X264_TYPE_BREF:
buf->s.frametype = HB_FRAME_BREF;
break;

// If it isn't the above, what type of frame is it??
case X264_TYPE_I:
default:
buf->s.frametype = 0;
buf->s.frametype = HB_FRAME_I;
break;
}
buf->s.flags = 0;

// PIR has no IDR frames, but x264 marks recovery points
// as keyframes. So fake an IDR at these points. This flag
// is also set for real IDR frames.
if (pic_out->b_keyframe)
{
buf->s.frametype = HB_FRAME_IDR;
buf->s.flags |= HB_FLAG_FRAMETYPE_KEY;
/* if we have a chapter marker pending and this
frame's presentation time stamp is at or after
the marker's time stamp, use this as the
Expand Down Expand Up @@ -728,17 +720,24 @@ static hb_buffer_t *nal_encode( hb_work_object_t *w, x264_picture_t *pic_out,
break;
}

/* Since libx264 doesn't tell us when b-frames are
themselves reference frames, figure it out on our own. */
if( (buf->s.frametype == HB_FRAME_B) &&
(nal[i].i_ref_idc != NAL_PRIORITY_DISPOSABLE) )
buf->s.frametype = HB_FRAME_BREF;

/* Expose disposable bit to muxer. */
if( nal[i].i_ref_idc == NAL_PRIORITY_DISPOSABLE )
buf->s.flags &= ~HB_FRAME_REF;
/*
* Expose disposable bit to muxer.
*
* Also, since libx264 doesn't tell us when B-frames are
* themselves reference frames, figure it out on our own.
*/
if (nal[i].i_ref_idc == NAL_PRIORITY_DISPOSABLE)
{
buf->s.flags &= ~HB_FLAG_FRAMETYPE_REF;
}
else
buf->s.flags |= HB_FRAME_REF;
{
if (buf->s.frametype == HB_FRAME_B)
{
buf->s.frametype = HB_FRAME_BREF;
}
buf->s.flags |= HB_FLAG_FRAMETYPE_REF;
}

buf->size += size;
}
Expand Down
18 changes: 12 additions & 6 deletions libhb/encx265.c
Original file line number Diff line number Diff line change
Expand Up @@ -384,11 +384,17 @@ static hb_buffer_t* nal_encode(hb_work_object_t *w,
{
return NULL;
}

buf->s.flags = 0;
buf->size = 0;

// copy the bitstream data
for (i = 0; i < nnal; i++)
{
if (HB_HEVC_NALU_KEYFRAME(nal[i].type))
{
buf->s.flags |= HB_FLAG_FRAMETYPE_REF;
buf->s.flags |= HB_FLAG_FRAMETYPE_KEY;
}
memcpy(buf->data + buf->size, nal[i].payload, nal[i].sizeBytes);
buf->size += nal[i].sizeBytes;
}
Expand All @@ -406,11 +412,10 @@ static hb_buffer_t* nal_encode(hb_work_object_t *w,
switch (pic_out->sliceType)
{
case X265_TYPE_IDR:
buf->s.flags |= HB_FLAG_FRAMETYPE_REF;
buf->s.flags |= HB_FLAG_FRAMETYPE_KEY;
buf->s.frametype = HB_FRAME_IDR;
break;
case X265_TYPE_I:
buf->s.frametype = HB_FRAME_I;
break;
case X265_TYPE_P:
buf->s.frametype = HB_FRAME_P;
break;
Expand All @@ -420,12 +425,13 @@ static hb_buffer_t* nal_encode(hb_work_object_t *w,
case X265_TYPE_BREF:
buf->s.frametype = HB_FRAME_BREF;
break;
case X265_TYPE_I:
default:
buf->s.frametype = 0;
buf->s.frametype = HB_FRAME_I;
break;
}

if (pic_out->sliceType == X265_TYPE_IDR)
if (buf->s.flags & HB_FLAG_FRAMETYPE_KEY)
{
hb_chapter_dequeue(pv->chapter_queue, buf);
}
Expand Down
4 changes: 4 additions & 0 deletions libhb/h265_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
#ifndef HB_H265_COMMON_H
#define HB_H265_COMMON_H

// inspired by libavcodec/hevc.h
// in HEVC, all "random access point" NAL units are keyframes
#define HB_HEVC_NALU_KEYFRAME(nal_unit_type) (((nal_unit_type) >= 16) && ((nal_unit_type) <= 23))

static const char * const hb_h265_tier_names[] = { "auto", "main", "high", NULL, };
static const char * const hb_h265_profile_names_8bit[] = { "auto", "main", "mainstillpicture", NULL, };
static const char * const hb_h265_profile_names_10bit[] = { "auto", "main10", "main10-intra", NULL, };
Expand Down
12 changes: 7 additions & 5 deletions libhb/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,23 +79,25 @@ struct hb_buffer_settings_s
#define HB_FRAME_P 0x10
#define HB_FRAME_B 0x20
#define HB_FRAME_BREF 0x40
#define HB_FRAME_KEY 0x0F
#define HB_FRAME_REF 0xF0
#define HB_FRAME_MASK_KEY 0x0F
#define HB_FRAME_MASK_REF 0xF0
uint8_t frametype;

// Picture flags used by filters
#ifndef PIC_FLAG_REPEAT_FIRST_FIELD
#define PIC_FLAG_REPEAT_FIRST_FIELD 0x0100
#endif
#ifndef PIC_FLAG_TOP_FIELD_FIRST
#define PIC_FLAG_TOP_FIELD_FIRST 0x0008
#endif
#ifndef PIC_FLAG_PROGRESSIVE_FRAME
#define PIC_FLAG_PROGRESSIVE_FRAME 0x0010
#endif
#ifndef PIC_FLAG_REPEAT_FIRST_FIELD
#define PIC_FLAG_REPEAT_FIRST_FIELD 0x0100
#endif
#define PIC_FLAG_REPEAT_FRAME 0x0200
#define HB_BUF_FLAG_EOF 0x0400
#define HB_BUF_FLAG_EOS 0x0800
#define HB_FLAG_FRAMETYPE_KEY 0x1000
#define HB_FLAG_FRAMETYPE_REF 0x2000
uint16_t flags;

#define HB_COMB_NONE 0
Expand Down
11 changes: 6 additions & 5 deletions libhb/muxavformat.c
Original file line number Diff line number Diff line change
Expand Up @@ -1161,14 +1161,15 @@ static int avformatMux(hb_mux_object_t *m, hb_mux_data_t *track, hb_buffer_t *bu
pkt.pts = pts;
pkt.duration = duration;

if (track->type == MUX_TYPE_VIDEO && ((job->vcodec & HB_VCODEC_H264_MASK) ||
(job->vcodec & HB_VCODEC_H265_MASK) ||
(job->vcodec & HB_VCODEC_FFMPEG_MASK)))
if (track->type == MUX_TYPE_VIDEO)
{
if (buf->s.frametype == HB_FRAME_IDR)
if ((buf->s.frametype == HB_FRAME_IDR) ||
(buf->s.flags & HB_FLAG_FRAMETYPE_KEY))
{
pkt.flags |= AV_PKT_FLAG_KEY;
}
}
else if (buf->s.frametype & HB_FRAME_KEY)
else if (buf->s.frametype & HB_FRAME_MASK_KEY)
{
pkt.flags |= AV_PKT_FLAG_KEY;
}
Expand Down
5 changes: 3 additions & 2 deletions libhb/qsv_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -2039,8 +2039,9 @@ uint8_t hb_qsv_frametype_xlat(uint16_t qsv_frametype, uint16_t *out_flags)
uint16_t flags = 0;
uint8_t frametype = 0;

if (qsv_frametype & MFX_FRAMETYPE_IDR)
if (qsv_frametype & MFX_FRAMETYPE_IDR)
{
flags |= HB_FLAG_FRAMETYPE_KEY;
frametype = HB_FRAME_IDR;
}
else if (qsv_frametype & MFX_FRAMETYPE_I)
Expand All @@ -2058,7 +2059,7 @@ uint8_t hb_qsv_frametype_xlat(uint16_t qsv_frametype, uint16_t *out_flags)

if (qsv_frametype & MFX_FRAMETYPE_REF)
{
flags |= HB_FRAME_REF;
flags |= HB_FLAG_FRAMETYPE_REF;
}

if (out_flags != NULL)
Expand Down
Loading

0 comments on commit a8b4a5a

Please sign in to comment.