From 728d6d42596d83f3fc8236f710ec1db7a2154d9f Mon Sep 17 00:00:00 2001
From: Gavin Hurlbut <gjhurlbu@gmail.com>
Date: Wed, 28 Jul 2010 18:08:07 -0700
Subject: [PATCH] Modified version of 6824-v1.patch from #6824
---
mythtv/libs/libmythtv/NuppelVideoPlayer.cpp | 3 +-
mythtv/libs/libmythtv/avformatdecoder.cpp | 146 +++++++++++++++++----------
mythtv/libs/libmythtv/avformatdecoder.h | 5 +-
mythtv/libs/libmythtv/playercontext.cpp | 3 +-
mythtv/libs/libmythtv/playercontext.h | 3 +
mythtv/libs/libmythtv/videoouttypes.h | 10 ++
mythtv/programs/mythcommflag/main.cpp | 17 +++
7 files changed, 131 insertions(+), 56 deletions(-)
diff --git a/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp b/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
index cfcda58..dd500ca 100644
a
|
b
|
int NuppelVideoPlayer::OpenFile(uint retries, bool allow_libmpeg2) |
942 | 942 | (player_ctx->IsPBP() && !player_ctx->IsPrimaryPBP()); |
943 | 943 | SetDecoder(new AvFormatDecoder(this, *player_ctx->playingInfo, |
944 | 944 | using_null_videoout, |
945 | | allow_libmpeg2, noaccel)); |
| 945 | allow_libmpeg2, noaccel, |
| 946 | player_ctx->GetSpecialDecode())); |
946 | 947 | } |
947 | 948 | player_ctx->UnlockPlayingInfo(__FILE__, __LINE__); |
948 | 949 | if (GetDecoder()) |
diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
index b99aba6..92413ce 100644
a
|
b
|
static int dts_decode_header(uint8_t *indata_ptr, int *rate, |
84 | 84 | int *nblks, int *sfreq); |
85 | 85 | static int encode_frame(bool dts, unsigned char* data, int len, |
86 | 86 | short *samples, int &samples_size); |
| 87 | static QSize get_video_dim(const AVCodecContext &ctx) |
| 88 | { |
| 89 | return QSize(ctx.width >> ctx.lowres, ctx.height >> ctx.lowres); |
| 90 | } |
| 91 | static float get_aspect(const AVCodecContext &ctx) |
| 92 | { |
| 93 | float aspect_ratio = 0.0f; |
| 94 | |
| 95 | if (ctx.sample_aspect_ratio.num && ctx.height) |
| 96 | { |
| 97 | aspect_ratio = av_q2d(ctx.sample_aspect_ratio) * (float) ctx.width; |
| 98 | aspect_ratio /= (float) ctx.height; |
| 99 | } |
| 100 | |
| 101 | if (aspect_ratio <= 0.0f || aspect_ratio > 6.0f) |
| 102 | { |
| 103 | if (ctx.height) |
| 104 | aspect_ratio = (float)ctx.width / (float)ctx.height; |
| 105 | else |
| 106 | aspect_ratio = 4.0f / 3.0f; |
| 107 | } |
| 108 | |
| 109 | return aspect_ratio; |
| 110 | } |
87 | 111 | |
88 | 112 | int get_avf_buffer_xvmc(struct AVCodecContext *c, AVFrame *pic); |
89 | 113 | int get_avf_buffer(struct AVCodecContext *c, AVFrame *pic); |
… |
… |
AvFormatDecoder::AvFormatDecoder(NuppelVideoPlayer *parent, |
476 | 500 | const ProgramInfo &pginfo, |
477 | 501 | bool use_null_videoout, |
478 | 502 | bool allow_libmpeg2, |
479 | | bool no_hardware_decode) |
| 503 | bool no_hardware_decode, |
| 504 | AVSpecialDecode special_decoding) |
480 | 505 | : DecoderBase(parent, pginfo), |
481 | 506 | d(new AvFormatDecoderPrivate(allow_libmpeg2)), |
482 | 507 | is_db_ignored(gCoreContext->IsDatabaseIgnored()), |
… |
… |
AvFormatDecoder::AvFormatDecoder(NuppelVideoPlayer *parent, |
495 | 520 | using_null_videoout(use_null_videoout), |
496 | 521 | video_codec_id(kCodec_NONE), |
497 | 522 | no_hardware_decoders(no_hardware_decode), |
| 523 | special_decode(special_decoding), |
498 | 524 | maxkeyframedist(-1), |
499 | 525 | // Closed Caption & Teletext decoders |
500 | 526 | ccd608(new CC608Decoder(parent->GetCC608Reader())), |
… |
… |
AvFormatDecoder::AvFormatDecoder(NuppelVideoPlayer *parent, |
536 | 562 | CC708Window::forceWhiteOnBlackText = true; |
537 | 563 | |
538 | 564 | no_dts_hack = false; |
| 565 | |
| 566 | int x = gContext->GetNumSetting("CommFlagFast", 0); |
| 567 | if (x) |
| 568 | special_decode = (AVSpecialDecode) x; |
| 569 | VERBOSE(VB_IMPORTANT, "commflagging_speedups: " << special_decode); |
539 | 570 | } |
540 | 571 | |
541 | 572 | AvFormatDecoder::~AvFormatDecoder() |
… |
… |
void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc, |
1385 | 1416 | <<") type ("<<codec_type_string(enc->codec_type) |
1386 | 1417 | <<")."); |
1387 | 1418 | |
1388 | | float aspect_ratio = 0.0; |
1389 | | |
1390 | 1419 | if (ringBuffer && ringBuffer->isDVD()) |
1391 | 1420 | directrendering = false; |
1392 | 1421 | |
1393 | | if (selectedStream) |
1394 | | { |
1395 | | fps = normalized_fps(stream, enc); |
1396 | | |
1397 | | if (enc->sample_aspect_ratio.num) |
1398 | | aspect_ratio = av_q2d(enc->sample_aspect_ratio); |
1399 | | else if (stream->sample_aspect_ratio.num) |
1400 | | aspect_ratio = av_q2d(stream->sample_aspect_ratio); |
1401 | | else |
1402 | | aspect_ratio = 1.0f; |
1403 | | |
1404 | | if (aspect_ratio <= 0.0f || aspect_ratio > 6.0f) |
1405 | | aspect_ratio = 1.0f; |
1406 | | |
1407 | | aspect_ratio *= (float)enc->width / (float)enc->height; |
1408 | | |
1409 | | current_width = enc->width; |
1410 | | current_height = enc->height; |
1411 | | current_aspect = aspect_ratio; |
1412 | | } |
1413 | | |
1414 | 1422 | enc->opaque = (void *)this; |
1415 | 1423 | enc->get_buffer = get_avf_buffer; |
1416 | 1424 | enc->release_buffer = release_avf_buffer; |
… |
… |
void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc, |
1482 | 1490 | .arg(codec_id_string(enc->codec_id))); |
1483 | 1491 | } |
1484 | 1492 | |
| 1493 | if (special_decode) |
| 1494 | { |
| 1495 | if (special_decode & kAVSpecialDecode_SingleThreaded) |
| 1496 | enc->thread_count = 1; |
| 1497 | |
| 1498 | enc->flags |= CODEC_FLAG2_FAST; |
| 1499 | |
| 1500 | if ((CODEC_ID_MPEG2VIDEO == codec->id) || |
| 1501 | (CODEC_ID_MPEG1VIDEO == codec->id)) |
| 1502 | { |
| 1503 | if (special_decode & kAVSpecialDecode_FewBlocks) |
| 1504 | { |
| 1505 | uint total_blocks = (enc->height+15) / 16; |
| 1506 | enc->skip_top = (total_blocks+3) / 4; |
| 1507 | enc->skip_bottom = (total_blocks+3) / 4; |
| 1508 | } |
| 1509 | |
| 1510 | if (special_decode & kAVSpecialDecode_LowRes) |
| 1511 | enc->lowres = 2; // 1 = 1/2 size, 2 = 1/4 size |
| 1512 | } |
| 1513 | else if (CODEC_ID_H264 == codec->id) |
| 1514 | { |
| 1515 | if (special_decode & kAVSpecialDecode_NoLoopFilter) |
| 1516 | { |
| 1517 | enc->flags &= ~CODEC_FLAG_LOOP_FILTER; |
| 1518 | enc->skip_loop_filter = AVDISCARD_ALL; |
| 1519 | } |
| 1520 | } |
| 1521 | |
| 1522 | if (special_decode & kAVSpecialDecode_NoDecode) |
| 1523 | { |
| 1524 | enc->skip_idct = AVDISCARD_ALL; |
| 1525 | } |
| 1526 | } |
| 1527 | |
1485 | 1528 | if (selectedStream) |
1486 | 1529 | { |
1487 | | uint width = enc->width; |
1488 | | uint height = enc->height; |
| 1530 | fps = normalized_fps(stream, enc); |
| 1531 | QSize dim = get_video_dim(*enc); |
| 1532 | int width = current_width = dim.width(); |
| 1533 | int height = current_height = dim.height(); |
| 1534 | float aspect = current_aspect = get_aspect(*enc); |
1489 | 1535 | |
1490 | | if (width == 0 && height == 0) |
| 1536 | if (!width || !height) |
1491 | 1537 | { |
1492 | 1538 | VERBOSE(VB_PLAYBACK, LOC + "InitVideoCodec " |
1493 | 1539 | "invalid dimensions, resetting decoder."); |
1494 | | width = 640; |
| 1540 | width = 640; |
1495 | 1541 | height = 480; |
1496 | | fps = 29.97; |
1497 | | aspect_ratio = 4.0 / 3; |
| 1542 | fps = 29.97f; |
| 1543 | aspect = 4.0f / 3.0f; |
1498 | 1544 | } |
1499 | 1545 | |
1500 | 1546 | GetNVP()->SetVideoParams(width, height, fps, |
1501 | | keyframedist, aspect_ratio, kScan_Detect, |
| 1547 | keyframedist, aspect, kScan_Detect, |
1502 | 1548 | dvd_video_codec_changed); |
1503 | 1549 | if (LCD *lcd = LCD::Get()) |
1504 | 1550 | { |
… |
… |
int AvFormatDecoder::ScanStreams(bool novideo) |
1911 | 1957 | d->DestroyMPEG2(); |
1912 | 1958 | m_h264_parser->Reset(); |
1913 | 1959 | |
1914 | | uint width = max(enc->width, 16); |
1915 | | uint height = max(enc->height, 16); |
| 1960 | QSize dim = get_video_dim(*enc); |
| 1961 | uint width = max(dim.width(), 16); |
| 1962 | uint height = max(dim.height(), 16); |
1916 | 1963 | QString dec = "ffmpeg"; |
1917 | 1964 | uint thread_count = 1; |
1918 | 1965 | |
… |
… |
void AvFormatDecoder::MpegPreProcessPkt(AVStream *stream, AVPacket *pkt) |
2922 | 2969 | SequenceHeader *seq = reinterpret_cast<SequenceHeader*>( |
2923 | 2970 | const_cast<uint8_t*>(bufptr)); |
2924 | 2971 | |
2925 | | uint width = seq->width(); |
2926 | | uint height = seq->height(); |
| 2972 | uint width = seq->width() >> context->lowres; |
| 2973 | uint height = seq->height() >> context->lowres; |
2927 | 2974 | float aspect = seq->aspect(context->sub_id == 1); |
2928 | 2975 | float seqFPS = seq->fps(); |
2929 | 2976 | |
2930 | | bool changed = (seqFPS > fps+0.01) || (seqFPS < fps-0.01); |
| 2977 | bool changed = (seqFPS > fps+0.01f) || (seqFPS < fps-0.01f); |
2931 | 2978 | changed |= (width != (uint)current_width ); |
2932 | 2979 | changed |= (height != (uint)current_height); |
2933 | 2980 | changed |= fabs(aspect - current_aspect) > eps; |
… |
… |
void AvFormatDecoder::MpegPreProcessPkt(AVStream *stream, AVPacket *pkt) |
2951 | 2998 | |
2952 | 2999 | // fps debugging info |
2953 | 3000 | float avFPS = normalized_fps(stream, context); |
2954 | | if ((seqFPS > avFPS+0.01) || (seqFPS < avFPS-0.01)) |
| 3001 | if ((seqFPS > avFPS+0.01f) || (seqFPS < avFPS-0.01f)) |
2955 | 3002 | { |
2956 | 3003 | VERBOSE(VB_PLAYBACK, LOC + |
2957 | 3004 | QString("avFPS(%1) != seqFPS(%2)") |
… |
… |
bool AvFormatDecoder::H264PreProcessPkt(AVStream *stream, AVPacket *pkt) |
3025 | 3072 | continue; |
3026 | 3073 | } |
3027 | 3074 | |
3028 | | float aspect_ratio; |
3029 | | if (context->sample_aspect_ratio.num == 0) |
3030 | | aspect_ratio = 0.0f; |
3031 | | else |
3032 | | aspect_ratio = av_q2d(context->sample_aspect_ratio) * |
3033 | | context->width / context->height; |
3034 | | |
3035 | | if (aspect_ratio <= 0.0f || aspect_ratio > 6.0f) |
3036 | | aspect_ratio = (float)context->width / context->height; |
3037 | | |
3038 | | uint width = context->width; |
3039 | | uint height = context->height; |
| 3075 | float aspect_ratio = get_aspect(*context); |
| 3076 | QSize dim = get_video_dim(*context); |
| 3077 | uint width = dim.width(); |
| 3078 | uint height = dim.height(); |
3040 | 3079 | float seqFPS = normalized_fps(stream, context); |
3041 | 3080 | |
3042 | | bool changed = (seqFPS > fps+0.01) || (seqFPS < fps-0.01); |
| 3081 | bool changed = (seqFPS > fps+0.01f) || (seqFPS < fps-0.01f); |
3043 | 3082 | changed |= (width != (uint)current_width ); |
3044 | 3083 | changed |= (height != (uint)current_height); |
3045 | 3084 | changed |= fabs(aspect_ratio - current_aspect) > eps; |
… |
… |
bool AvFormatDecoder::H264PreProcessPkt(AVStream *stream, AVPacket *pkt) |
3061 | 3100 | |
3062 | 3101 | // fps debugging info |
3063 | 3102 | float avFPS = normalized_fps(stream, context); |
3064 | | if ((seqFPS > avFPS+0.01) || (seqFPS < avFPS-0.01)) |
| 3103 | if ((seqFPS > avFPS+0.01f) || (seqFPS < avFPS-0.01f)) |
3065 | 3104 | { |
3066 | 3105 | VERBOSE(VB_PLAYBACK, LOC + |
3067 | 3106 | QString("avFPS(%1) != seqFPS(%2)") |
… |
… |
bool AvFormatDecoder::ProcessVideoPacket(AVStream *curstream, AVPacket *pkt) |
3200 | 3239 | tmppicture.linesize[1] = picframe->pitches[1]; |
3201 | 3240 | tmppicture.linesize[2] = picframe->pitches[2]; |
3202 | 3241 | |
| 3242 | QSize dim = get_video_dim(*context); |
3203 | 3243 | sws_ctx = sws_getCachedContext(sws_ctx, context->width, |
3204 | 3244 | context->height, context->pix_fmt, |
3205 | 3245 | context->width, context->height, |
… |
… |
bool AvFormatDecoder::ProcessVideoPacket(AVStream *curstream, AVPacket *pkt) |
3210 | 3250 | VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to allocate sws context"); |
3211 | 3251 | return false; |
3212 | 3252 | } |
3213 | | sws_scale(sws_ctx, mpa_pic.data, mpa_pic.linesize, 0, context->height, |
| 3253 | sws_scale(sws_ctx, mpa_pic.data, mpa_pic.linesize, 0, dim.height(), |
3214 | 3254 | tmppicture.data, tmppicture.linesize); |
3215 | 3255 | |
3216 | 3256 | |
… |
… |
bool AvFormatDecoder::GetFrame(DecodeType decodetype) |
4380 | 4420 | |
4381 | 4421 | if (!d->HasMPEG2Dec()) |
4382 | 4422 | { |
4383 | | int current_width = curstream->codec->width; |
| 4423 | int current_width = curstream->codec->width; // TODO CHECKME |
4384 | 4424 | int video_width = GetNVP()->GetVideoSize().width(); |
4385 | 4425 | if (dvd_xvmc_enabled && GetNVP() && GetNVP()->getVideoOutput()) |
4386 | 4426 | { |
diff --git a/mythtv/libs/libmythtv/avformatdecoder.h b/mythtv/libs/libmythtv/avformatdecoder.h
index a7454d2..04774d5 100644
a
|
b
|
|
2 | 2 | #define AVFORMATDECODER_H_ |
3 | 3 | |
4 | 4 | #include <QString> |
| 5 | #include <QMap> |
5 | 6 | #include <QList> |
6 | 7 | |
7 | 8 | #include "programinfo.h" |
… |
… |
class AvFormatDecoder : public DecoderBase |
79 | 80 | static void GetDecoders(render_opts &opts); |
80 | 81 | AvFormatDecoder(NuppelVideoPlayer *parent, const ProgramInfo &pginfo, |
81 | 82 | bool use_null_video_out, bool allow_libmpeg2 = true, |
82 | | bool no_hardware_decode = false); |
| 83 | bool no_hardware_decode = false, |
| 84 | AVSpecialDecode av_special_decode = kAVSpecialDecode_None); |
83 | 85 | ~AvFormatDecoder(); |
84 | 86 | |
85 | 87 | void CloseCodecs(); |
… |
… |
class AvFormatDecoder : public DecoderBase |
264 | 266 | bool using_null_videoout; |
265 | 267 | MythCodecID video_codec_id; |
266 | 268 | bool no_hardware_decoders; |
| 269 | AVSpecialDecode special_decode; |
267 | 270 | |
268 | 271 | int maxkeyframedist; |
269 | 272 | |
diff --git a/mythtv/libs/libmythtv/playercontext.cpp b/mythtv/libs/libmythtv/playercontext.cpp
index a102568..46d8ca8 100644
a
|
b
|
void PlayerThread::run(void) |
37 | 37 | PlayerContext::PlayerContext(const QString &inUseID) : |
38 | 38 | recUsage(inUseID), nvp(NULL), nvpUnsafe(false), recorder(NULL), |
39 | 39 | tvchain(NULL), buffer(NULL), playingInfo(NULL), |
40 | | playingLen(0), nohardwaredecoders(false), last_cardid(-1), last_framerate(30.0f), |
| 40 | playingLen(0), specialDecode(kAVSpecialDecode_None), |
| 41 | nohardwaredecoders(false), last_cardid(-1), last_framerate(30.0f), |
41 | 42 | // Fast forward state |
42 | 43 | ff_rew_state(0), ff_rew_index(0), ff_rew_speed(0), |
43 | 44 | // Other state |
diff --git a/mythtv/libs/libmythtv/playercontext.h b/mythtv/libs/libmythtv/playercontext.h
index 2b0e518..756d4bd 100644
a
|
b
|
class MPUBLIC PlayerContext |
119 | 119 | void SetPIPState(PIPState change) { pipState = change; } |
120 | 120 | void SetNVPChangingBuffers(bool val) { nvpUnsafe = val; } |
121 | 121 | void SetNoHardwareDecoders(void) { nohardwaredecoders = true; } |
| 122 | void SetSpecialDecode(AVSpecialDecode sp) { specialDecode = sp; } |
122 | 123 | |
123 | 124 | // Gets |
124 | 125 | QRect GetStandAlonePIPRect(void); |
… |
… |
class MPUBLIC PlayerContext |
131 | 132 | QString GetPlayMessage(void) const; |
132 | 133 | TVState GetState(void) const; |
133 | 134 | bool GetPlayingInfoMap(InfoMap &infoMap) const; |
| 135 | AVSpecialDecode GetSpecialDecode(void) const { return specialDecode; } |
134 | 136 | |
135 | 137 | // Boolean Gets |
136 | 138 | bool IsPIPSupported(void) const; |
… |
… |
class MPUBLIC PlayerContext |
169 | 171 | RingBuffer *buffer; |
170 | 172 | ProgramInfo *playingInfo; ///< Currently playing info |
171 | 173 | long long playingLen; ///< Initial CalculateLength() |
| 174 | AVSpecialDecode specialDecode; |
172 | 175 | bool nohardwaredecoders; // < Disable use of VDPAU decoding |
173 | 176 | int last_cardid; ///< CardID of current/last recorder |
174 | 177 | float last_framerate; ///< Estimated framerate from recorder |
diff --git a/mythtv/libs/libmythtv/videoouttypes.h b/mythtv/libs/libmythtv/videoouttypes.h
index 37b9517..b3401a3 100644
a
|
b
|
typedef enum VideoErrorState |
109 | 109 | kError_Switch_Renderer = 0x04, // Current renderer is not preferred choice |
110 | 110 | } VideoErrorState; |
111 | 111 | |
| 112 | typedef enum AVSpecialDecode |
| 113 | { |
| 114 | kAVSpecialDecode_None = 0x00, |
| 115 | kAVSpecialDecode_LowRes = 0x01, |
| 116 | kAVSpecialDecode_SingleThreaded = 0x02, |
| 117 | kAVSpecialDecode_FewBlocks = 0x04, |
| 118 | kAVSpecialDecode_NoLoopFilter = 0x08, |
| 119 | kAVSpecialDecode_NoDecode = 0x10, |
| 120 | } AVSpecialDecode; |
| 121 | |
112 | 122 | inline bool is_interlaced(FrameScanType scan) |
113 | 123 | { |
114 | 124 | return (kScan_Interlaced == scan) || (kScan_Intr2ndField == scan); |
diff --git a/mythtv/programs/mythcommflag/main.cpp b/mythtv/programs/mythcommflag/main.cpp
index 1d745cd..a24600a 100644
a
|
b
|
int BuildVideoMarkup(ProgramInfo *program_info, bool useDB) |
172 | 172 | |
173 | 173 | MythCommFlagPlayer *cfp = new MythCommFlagPlayer(); |
174 | 174 | PlayerContext *ctx = new PlayerContext("seektable rebuilder"); |
| 175 | ctx->SetSpecialDecode(kAVSpecialDecode_NoDecode); |
175 | 176 | ctx->SetPlayingInfo(program_info); |
176 | 177 | ctx->SetRingBuffer(tmprbuf); |
177 | 178 | ctx->SetNVP(cfp); |
… |
… |
int FlagCommercials( |
756 | 757 | MythCommFlagPlayer *cfp = new MythCommFlagPlayer(); |
757 | 758 | |
758 | 759 | PlayerContext *ctx = new PlayerContext(kFlaggerInUseID); |
| 760 | |
| 761 | AVSpecialDecode sp = (AVSpecialDecode) |
| 762 | (kAVSpecialDecode_LowRes | |
| 763 | kAVSpecialDecode_SingleThreaded | |
| 764 | kAVSpecialDecode_NoLoopFilter); |
| 765 | |
| 766 | #if 0 /* blank detector needs to be only sample center for this optimization. */ |
| 767 | if ((COMM_DETECT_BLANKS == commDetectMethod) || |
| 768 | (COMM_DETECT_2_BLANK == commDetectMethod)) |
| 769 | { |
| 770 | sp = (AVSpecialDecode) (sp | kAVSpecialDecode_FewBlocks); |
| 771 | } |
| 772 | #endif |
| 773 | |
| 774 | ctx->SetSpecialDecode(sp); |
| 775 | |
759 | 776 | ctx->SetPlayingInfo(program_info); |
760 | 777 | ctx->SetRingBuffer(tmprbuf); |
761 | 778 | ctx->SetNVP(cfp); |