From 8e96e2e4f3e0ae86fdcf03b742ecf82eff905cc9 Mon Sep 17 00:00:00 2001 From: Chris Pinkham Date: Fri, 20 Jul 2012 15:02:08 -0700 Subject: [PATCH] HLS/--avf encoder fixes. - Fix blockiness at stream startup. Due to the video frames buffered in the encoder, the frames we were tagging as keyframes in the output files weren't actually the keyframes. - Simplify profile and level calculations. If output width is over 480 pixels or output video bitrate is over 600Kbit, then use Main 3.1, otherwise use Baseline 3.0. - Change default output width and bitrate to 480 and 600Kbit so that Baseline 3.0 is used by default. - Set keyframe distance to 30 for --avf mode. - Don't look for the MARK_UPDATED_CUT markup when in --avf mode - Don't clear the seektables when running in --avf mode --- mythtv/libs/libmythtv/avformatwriter.cpp | 30 ++++++++------------- mythtv/programs/mythtranscode/transcode.cpp | 10 ++++--- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/mythtv/libs/libmythtv/avformatwriter.cpp b/mythtv/libs/libmythtv/avformatwriter.cpp index 6435a31d810..9c2014f3449 100644 --- a/mythtv/libs/libmythtv/avformatwriter.cpp +++ b/mythtv/libs/libmythtv/avformatwriter.cpp @@ -253,6 +253,7 @@ int AVFormatWriter::WriteVideoFrame(VideoFrame *frame) uint8_t *planes[3]; int len = frame->size; unsigned char *buf = frame->buf; + int framesEncoded = m_framesWritten + m_bufferedVideoFrameTimes.size(); planes[0] = buf; planes[1] = planes[0] + frame->width * frame->height; @@ -265,10 +266,10 @@ int AVFormatWriter::WriteVideoFrame(VideoFrame *frame) m_picture->linesize[0] = frame->width; m_picture->linesize[1] = frame->width / 2; m_picture->linesize[2] = frame->width / 2; - m_picture->pts = m_framesWritten + 1; + m_picture->pts = framesEncoded + 1; m_picture->type = FF_BUFFER_TYPE_SHARED; - if ((m_framesWritten % m_keyFrameDist) == 0) + if ((framesEncoded % m_keyFrameDist) == 0) m_picture->pict_type = AV_PICTURE_TYPE_I; else m_picture->pict_type = AV_PICTURE_TYPE_NONE; @@ -301,15 +302,16 @@ int AVFormatWriter::WriteVideoFrame(VideoFrame *frame) return ret; } - if ((m_framesWritten % m_keyFrameDist) == 0) - m_pkt->flags |= AV_PKT_FLAG_KEY; - long long tc = frame->timecode; if (!m_bufferedVideoFrameTimes.isEmpty()) tc = m_bufferedVideoFrameTimes.takeFirst(); if (!m_bufferedVideoFrameTypes.isEmpty()) - m_bufferedVideoFrameTypes.pop_front(); + { + int pict_type = m_bufferedVideoFrameTypes.takeFirst(); + if (pict_type == AV_PICTURE_TYPE_I) + m_pkt->flags |= AV_PKT_FLAG_KEY; + } if (m_startingTimecodeOffset == -1) m_startingTimecodeOffset = tc; @@ -495,20 +497,9 @@ AVStream* AVFormatWriter::AddVideoStream(void) } else if (c->codec_id == CODEC_ID_H264) { - av_opt_set(c->priv_data, "profile", "baseline", 0); - if ((c->height <= 240) && - (c->width <= 320) && - (c->bit_rate <= 768000)) - { - c->level = 13; - } - else if (c->width >= 1024) - { - c->level = 41; - av_opt_set(c->priv_data, "profile", "high", 0); - } - else if (c->width >= 960) + if ((c->width > 480) || + (c->bit_rate > 600000)) { c->level = 31; av_opt_set(c->priv_data, "profile", "main", 0); @@ -516,6 +507,7 @@ AVStream* AVFormatWriter::AddVideoStream(void) else { c->level = 30; + av_opt_set(c->priv_data, "profile", "baseline", 0); } c->coder_type = 0; diff --git a/mythtv/programs/mythtranscode/transcode.cpp b/mythtv/programs/mythtranscode/transcode.cpp index 11ed31394b3..f4e476f5f0e 100755 --- a/mythtv/programs/mythtranscode/transcode.cpp +++ b/mythtv/programs/mythtranscode/transcode.cpp @@ -726,7 +726,7 @@ Transcode::Transcode(ProgramInfo *pginfo) : cmdContainer("mpegts"), cmdAudioCodec("aac"), cmdVideoCodec("libx264"), cmdWidth(480), cmdHeight(0), - cmdBitrate(800000), cmdAudioBitrate(64000) + cmdBitrate(600000), cmdAudioBitrate(64000) { } @@ -1180,6 +1180,7 @@ int Transcode::TranscodeFile(const QString &inputname, avfw->SetAudioCodec(cmdAudioCodec); avfw->SetFilename(outputname); avfw->SetFramerate(video_frame_rate); + avfw->SetKeyFrameDist(30); } avfw->SetThreadCount( @@ -2015,7 +2016,8 @@ int Transcode::TranscodeFile(const QString &inputname, if (avfw->WriteVideoFrame(&frame) > 0) { lastWrittenTime = frame.timecode; - ++hlsSegmentFrames; + if (hls) + ++hlsSegmentFrames; } } @@ -2049,7 +2051,7 @@ int Transcode::TranscodeFile(const QString &inputname, } if (MythDate::current() > curtime) { - if (honorCutList && m_proginfo && !hls && + if (honorCutList && m_proginfo && !avfMode && m_proginfo->QueryMarkupFlag(MARK_UPDATED_CUT)) { LOG(VB_GENERAL, LOG_NOTICE, @@ -2117,7 +2119,7 @@ int Transcode::TranscodeFile(const QString &inputname, if (avfw2) avfw2->CloseFile(); - if (!hls && m_proginfo) + if (!avfMode && m_proginfo) { m_proginfo->ClearPositionMap(MARK_KEYFRAME); m_proginfo->ClearPositionMap(MARK_GOP_START);