[mythtv-users] mythcommflag prob (was How to transcode HD recording)
HP-mini
blm-ubunet at slingshot.co.nz
Thu Jan 23 06:19:00 UTC 2014
On Wed, 2014-01-15 at 22:35 +0000, John Pilkington wrote:
> On 15/01/14 20:20, HP-mini wrote:
>
> <snip>
> I'm not sure how long a clip I can send; last time I tried there seemed
> to be some sort of threshold at 50 MB.
>
> This is from BBC TWO HD DVB-T2 Wild Brazil, 1102_20140115212800.mpg
>
> dd bs=1M count=48 if=Braz.mpg of=Braz_dd.mpg
>
> http://www.mediafire.com/watch/51w0355pga4bb8w/Braz_dd.mpg
> http://www.mediafire.com/view/hl356ki6az461gq/Braz_orig.xml
> http://www.mediafire.com/view/mzysobexws83yw6/Braz_rebuilt.xml
>
>
The attached patch appears to generate a usable seektable on your 2
recordings without causing trouble with HDPVR samples or my local
recordings.
The cutlist editor & player seeks cleanly..
I have not confirmed the exact positions with independent tool.
The stream analyzer s/w (I have) is trial/demo & will not run in
virtualbox.
The keyframe positions in the 1st recording clip (simpsons) do seem odd.
The patch just flips around the keyframe search order in
avformatdecoder.. The other changes are mostly just cleanup.
YMMV..
-------------- next part --------------
diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
index 3a42b40..f61a8fa 100644
--- a/mythtv/libs/libmythtv/avformatdecoder.cpp
+++ b/mythtv/libs/libmythtv/avformatdecoder.cpp
@@ -354,7 +354,7 @@ AvFormatDecoder::AvFormatDecoder(MythPlayer *parent,
cc608_build_parity_table(cc608_parity_table);
- SetIdrOnlyKeyframes(true);
+ SetIdrOnlyKeyframes(false);
LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("PlayerFlags: 0x%1")
.arg(playerFlags, 0, 16));
@@ -3152,7 +3152,7 @@ int AvFormatDecoder::H264PreProcessPkt(AVStream *stream, AVPacket *pkt)
if (m_h264_parser->onFrameStart())
++num_frames;
- if (!m_h264_parser->onKeyFrameStart())
+ if (!m_h264_parser->onKeyFrameStart() || !m_h264_parser->seen_SPS())
continue;
}
else
diff --git a/mythtv/libs/libmythtv/mpeg/H264Parser.cpp b/mythtv/libs/libmythtv/mpeg/H264Parser.cpp
index d0eebde..db79855 100644
--- a/mythtv/libs/libmythtv/mpeg/H264Parser.cpp
+++ b/mythtv/libs/libmythtv/mpeg/H264Parser.cpp
@@ -115,9 +115,9 @@ void H264Parser::Reset(void)
slice_type = SLICE_UNDEF;
prev_pic_parameter_set_id = pic_parameter_set_id = -1;
prev_field_pic_flag = field_pic_flag = -1;
- prev_bottom_field_flag = bottom_field_flag = -1;
- prev_nal_ref_idc = nal_ref_idc = 111; // != [0|1|2|3]
- prev_pic_order_cnt_type = pic_order_cnt_type =
+ prev_bottom_field_flag = bottom_field_flag = 0;
+ prev_nal_ref_idc = nal_ref_idc = 0;
+ prev_pic_order_cnt_type = pic_order_cnt_type = 0;
prev_pic_order_cnt_lsb = pic_order_cnt_lsb = 0;
prev_delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom = 0;
prev_delta_pic_order_cnt[0] = delta_pic_order_cnt[0] = 0;
@@ -125,7 +125,7 @@ void H264Parser::Reset(void)
prev_nal_unit_type = nal_unit_type = UNKNOWN;
// The value of idr_pic_id shall be in the range of 0 to 65535, inclusive.
- prev_idr_pic_id = idr_pic_id = 65536;
+ prev_idr_pic_id = idr_pic_id = -1;
log2_max_frame_num = log2_max_pic_order_cnt_lsb = 0;
seq_parameter_set_id = 0;
@@ -146,9 +146,10 @@ void H264Parser::Reset(void)
frame_crop_top_offset = frame_crop_bottom_offset = 0;
aspect_ratio_idc = 0;
sar_width = sar_height = 0;
- unitsInTick = 0;
+ prev_unitsInTick = 1; unitsInTick = 0;
timeScale = 0;
fixedRate = 0;
+ stream_changed = false;
pkt_offset = AU_offset = frame_start_offset = keyframe_start_offset = 0;
on_frame = on_key_frame = false;
@@ -260,7 +261,7 @@ bool H264Parser::new_AU(void)
*/
- bool result = false;
+ bool result = false;
if (prev_frame_num != -1)
{
@@ -273,7 +274,7 @@ bool H264Parser::new_AU(void)
result = true;
else if (field_pic_flag != prev_field_pic_flag)
result = true;
- else if ((bottom_field_flag != -1 && prev_bottom_field_flag != -1) &&
+ else if ((bottom_field_flag != 0 && prev_bottom_field_flag != 0) &&
bottom_field_flag != prev_bottom_field_flag)
result = true;
else if ((nal_ref_idc == 0 || prev_nal_ref_idc == 0) &&
@@ -297,6 +298,7 @@ bool H264Parser::new_AU(void)
idr_pic_id != prev_idr_pic_id)
result = true;
}
+ result |= au_contains_keyframe_message;
prev_frame_num = frame_num;
prev_pic_parameter_set_id = pic_parameter_set_id;
@@ -639,7 +641,7 @@ bool H264Parser::decode_Header(GetBitContext *gb)
that precedes the current slice in decoding order and has the
same value of colour_plane_id.
*/
- /* uint first_mb_in_slice = */ get_ue_golomb(gb);
+ /* uint first_mb_in_slice = */ get_ue_golomb_long(gb);
/*
slice_type specifies the coding type of the slice according to
@@ -718,13 +720,19 @@ bool H264Parser::decode_Header(GetBitContext *gb)
such IDR access unit shall differ from the idr_pic_id in the
second such IDR access unit. The value of idr_pic_id shall be in
the range of 0 to 65535, inclusive.
+
+ 7.4.3
+ If the current picture is an IDR picture, PrevRefFrameNum is set equal to 0
+ but 7.4.1.2.4 says prev_frame_num raw header value is used for AU detection
+ prev_frame_num = 0; // but only for decoding process
*/
+
if (nal_unit_type == SLICE_IDR)
{
idr_pic_id = get_ue_golomb(gb);
is_keyframe = true;
}
- else
+ else // option all I frames as keyframes.
is_keyframe = (I_is_keyframe && isKeySlice(slice_type));
/*
@@ -1261,6 +1269,11 @@ void H264Parser::vui_parameters(GetBitContext * gb)
sar_height = get_bits(gb, 16);
break;
}
+ if (aspect_ratio_idc != prev_aspect_ratio_idc)
+ {
+ stream_changed = true;
+ prev_aspect_ratio_idc = aspect_ratio_idc;
+ }
}
else
sar_width = sar_height = 0;
@@ -1291,6 +1304,11 @@ void H264Parser::vui_parameters(GetBitContext * gb)
unitsInTick = get_bits_long(gb, 32); //num_units_in_tick
timeScale = get_bits_long(gb, 32); //time_scale
fixedRate = get_bits1(gb);
+ if (unitsInTick != prev_unitsInTick)
+ {
+ stream_changed = true;
+ prev_unitsInTick = unitsInTick;
+ }
}
}
diff --git a/mythtv/libs/libmythtv/mpeg/H264Parser.h b/mythtv/libs/libmythtv/mpeg/H264Parser.h
index ad78946..5874c45 100644
--- a/mythtv/libs/libmythtv/mpeg/H264Parser.h
+++ b/mythtv/libs/libmythtv/mpeg/H264Parser.h
@@ -94,22 +94,22 @@ class H264Parser {
slice_type – 5.
*/
enum SLICE_type {
- SLICE_P = 0,
- SLICE_B = 1,
- SLICE_I = 2,
- SLICE_SP = 3,
- SLICE_SI = 4,
- SLICE_P_a = 5,
- SLICE_B_a = 6,
- SLICE_I_a = 7,
- SLICE_SP_a = 8,
- SLICE_SI_a = 9,
+ SLICE_P = 0,
+ SLICE_B = 1,
+ SLICE_I = 2,
+ SLICE_SP = 3,
+ SLICE_SI = 4,
+ SLICE_P_a = 5,
+ SLICE_B_a = 6,
+ SLICE_I_a = 7,
+ SLICE_SP_a = 8,
+ SLICE_SI_a = 9,
SLICE_UNDEF = 10
};
enum frame_type {
- FRAME = 'F',
- FIELD_TOP = 'T',
+ FRAME = 'F',
+ FIELD_TOP = 'T',
FIELD_BOTTOM = 'B'
};
@@ -214,6 +214,7 @@ class H264Parser {
bool au_contains_keyframe_message;
bool is_keyframe;
bool I_is_keyframe;
+ bool stream_changed;
uint32_t sync_accumulator;
uint8_t *rbsp_buffer;
@@ -253,9 +254,9 @@ class H264Parser {
uint frame_crop_right_offset;
uint frame_crop_top_offset;
uint frame_crop_bottom_offset;
- uint8_t aspect_ratio_idc;
+ uint8_t aspect_ratio_idc, prev_aspect_ratio_idc;
uint sar_width, sar_height;
- uint32_t unitsInTick, timeScale;
+ uint32_t unitsInTick, prev_unitsInTick, timeScale;
bool fixedRate;
uint64_t pkt_offset, AU_offset, frame_start_offset, keyframe_start_offset;
diff --git a/mythtv/libs/libmythtv/mythcommflagplayer.cpp b/mythtv/libs/libmythtv/mythcommflagplayer.cpp
index b521e01..361c051 100644
--- a/mythtv/libs/libmythtv/mythcommflagplayer.cpp
+++ b/mythtv/libs/libmythtv/mythcommflagplayer.cpp
@@ -106,7 +106,7 @@ bool MythCommFlagPlayer::RebuildSeekTable(
cout << "\r \r" << flush;
int prevperc = -1;
- bool usingIframes = false;
+ bool usingIframes = true;
while (GetEof() == kEofStateNone)
{
if (inuse_timer.elapsed() > 2534)
@@ -182,25 +182,25 @@ bool MythCommFlagPlayer::RebuildSeekTable(
if (DecoderGetFrame(kDecodeNothing,true))
myFramesPlayed = decoder->GetFramesRead();
- // H.264 recordings from an HD-PVR contain IDR keyframes,
- // which are the only valid cut points for lossless cuts.
- // However, DVB-S h.264 recordings may lack IDR keyframes, in
- // which case we need to allow non-IDR I-frames. If we get
- // far enough into the rebuild without having created any
- // seektable entries, we can assume it is because of the IDR
- // keyframe setting, and so we rewind and allow h.264 non-IDR
- // I-frames to be treated as keyframes.
+ // H.264 recordings from an HD-PVR contain IDR keyframes
+ // and are the only valid cut points for lossless cuts.
+ // DVB-S(2)/T(2) H.264 recordings typically do not use
+ // IDR keyframes & do not use I frames as keyframes.
+ // If we get far enough into the rebuild without having created any
+ // seektable entries, we assume it is because of the IDR
+ // keyframe setting, and so we rewind and allow H.264 IDR
+ // (HD-PVR type) detection.
uint64_t frames = decoder->GetFramesRead();
- if (!usingIframes &&
- (GetEof() != kEofStateNone || (frames > 1000 && frames < 1100)) &&
+ if (usingIframes &&
+ (GetEof() != kEofStateNone || (frames > 100 && frames < 1100)) &&
!decoder->HasPositionMap())
{
- cout << "No I-frames found, rewinding..." << endl;
+ cout << "No non-IDR keyframes found, rewinding..." << endl;
decoder->DoRewind(0);
decoder->Reset(true, true, true);
pmap_first = pmap_last = myFramesPlayed = 0;
- decoder->SetIdrOnlyKeyframes(false);
- usingIframes = true;
+ decoder->SetIdrOnlyKeyframes(true);
+ usingIframes = false;
}
}
More information about the mythtv-users
mailing list