Ticket #10793: comm-detector-audio.1.patch
| File comm-detector-audio.1.patch, 54.0 KB (added by , 14 years ago) |
|---|
-
new file mythtv/programs/mythcommflag/AudioBuffer.cpp
commit 7cef0613cac0cac57ec6bf36ba99cc8bc247a49f Author: Mark Spieth <mspieth@digivation.com.au> Date: Wed Jan 5 10:49:43 2011 +1100 audio addon for comm detector diff --git a/mythtv/programs/mythcommflag/AudioBuffer.cpp b/mythtv/programs/mythcommflag/AudioBuffer.cpp new file mode 100644 index 0000000..4f789fc- + 1 2 #include "AudioBuffer.h" 3 4 AudioSample::AudioSample() 5 { 6 time = 0; 7 duration = 0; 8 power = 0; 9 channels = 0; 10 changed = false; 11 } 12 13 QString AudioSample::toString() const 14 { 15 return QString("%1 %2 %3 %4 %5") 16 .arg(time) 17 .arg(duration) 18 .arg(power) 19 .arg(channels) 20 .arg(changed); 21 } 22 23 24 AudioBuffer::AudioBuffer(const AudioSettings &settings) : 25 configured_channels(CHANNELS_MAX), 26 last_audiotime(0), 27 output_settings(0), 28 changed(false), 29 info_valid(false), 30 m_lock(), 31 verboseDebugging(false), 32 enabled(false) 33 { 34 if (getenv("DEBUGCOMMFLAG")) 35 verboseDebugging = true; 36 37 Reset(); 38 //AudioSettings orig_settings("", "", AudioFormat::,); 39 //Reconfigure(audio_bits, audio_channels, 0); 40 Reconfigure(settings); 41 } 42 43 AudioBuffer::~AudioBuffer() 44 { 45 //delete [] audiobuffer; 46 if (output_settings) 47 { 48 delete output_settings; 49 output_settings = NULL; 50 } 51 } 52 53 AudioOutputSettings* AudioBuffer::GetOutputSettings(bool /*digital*/) 54 { 55 AudioOutputSettings *settings = new AudioOutputSettings(); 56 57 for (uint channels = CHANNELS_MIN; channels <= CHANNELS_MAX; channels++) 58 { 59 settings->AddSupportedChannels(channels); 60 } 61 62 LOG(VB_COMMFLAG, LOG_INFO, 63 QString("GetOutputSettings")); 64 return settings; 65 } 66 67 AudioOutputSettings* AudioBuffer::GetOutputSettingsUsers(bool digital) 68 { 69 if (!output_settings) 70 output_settings = GetOutputSettings(digital); 71 return output_settings; 72 } 73 74 AudioOutputSettings* AudioBuffer::GetOutputSettingsCleaned(bool digital) 75 { 76 if (!output_settings) 77 output_settings = GetOutputSettings(digital); 78 return output_settings; 79 } 80 81 void AudioBuffer::Enable() 82 { 83 enabled = true; 84 } 85 86 // reconfigure sound out for new params 87 void AudioBuffer::Reconfigure(const AudioSettings &orig_settings) 88 { 89 ClearError(); 90 changed = (orig_settings.format != settings.format) 91 | (orig_settings.channels != settings.channels) 92 | (orig_settings.samplerate != settings.samplerate); 93 settings = orig_settings; 94 95 source_bytes_per_frame = source_channels * AudioOutputSettings::SampleSize(settings.format); 96 LOG(VB_COMMFLAG, LOG_INFO, 97 QString("Audio Reconfigure changed %1.").arg(changed)); 98 99 QMutexLocker locker(&m_lock); 100 audioSamples.clear(); 101 last_audiotime = 0; 102 } 103 104 // dsprate is in 100 * samples/second 105 void AudioBuffer::SetEffDsp(int /* dsprate */) 106 { 107 //eff_audiorate = (dsprate / 100); 108 } 109 110 void AudioBuffer::SetBlocking(bool block) 111 { 112 (void)block; 113 } 114 115 void AudioBuffer::Reset(void) 116 { 117 if (!enabled) 118 return; 119 if (verboseDebugging) 120 { 121 LOG(VB_COMMFLAG, LOG_DEBUG, 122 QString("audio reset")); 123 } 124 QMutexLocker locker(&m_lock); 125 audioSamples.clear(); 126 last_audiotime = 0; 127 } 128 129 bool AudioBuffer::AddFrames(void *in_buffer, int in_frames, 130 int64_t timecode) 131 { 132 if (!enabled) 133 { 134 last_audiotime = timecode; 135 return true; 136 } 137 return AddData(in_buffer, in_frames * source_bytes_per_frame, timecode, 138 in_frames); 139 } 140 141 bool AudioBuffer::AddData(void *in_buffer, int in_len, 142 int64_t timecode, int in_frames) 143 { 144 if (!enabled) 145 { 146 last_audiotime = timecode; 147 return true; 148 } 149 int i; 150 int f; 151 PAudioSample aSample(new AudioSample); 152 aSample->power = 0; 153 aSample->time = timecode; // in ms 154 aSample->duration = (in_frames * 1000) / settings.samplerate; // in ms 155 aSample->channels = settings.channels; 156 if (changed) 157 { 158 aSample->changed = changed; 159 changed = false; 160 } 161 if (timecode < last_audiotime) 162 { 163 LOG(VB_COMMFLAG, LOG_DEBUG, 164 QString("audio time reset %1").arg(timecode)); 165 QMutexLocker locker(&m_lock); 166 audioSamples.clear(); 167 last_audiotime = 0; 168 } 169 if (last_audiotime != 0) 170 { 171 int64_t nextAudiotime = last_audiotime + aSample->duration; 172 while (aSample->time < nextAudiotime) 173 { 174 PAudioSample nullSample(new AudioSample); 175 nullSample->power = -1; 176 nullSample->time = nextAudiotime; 177 nullSample->duration = aSample->duration; 178 { 179 QMutexLocker locker(&m_lock); 180 audioSamples.push_back(nullSample); 181 } 182 #ifdef AUDIODEBUGGING 183 LOG(VB_COMMFLAG, LOG_DEBUG, 184 QString("Audio AddData invalid time %1").arg(nullSample->time)); 185 #endif 186 } 187 } 188 switch (settings.format) 189 { 190 case FORMAT_S16: 191 { 192 int64_t power = 0; 193 int16_t *p = (int16_t*)in_buffer; 194 for(f=in_frames;f>0;--f) 195 { 196 // power as mono 197 int64_t sum = 0; 198 for(i=settings.channels; i>0; --i) 199 { 200 sum += *p++; 201 p++; 202 } 203 power += sum * sum; 204 } 205 aSample->power += ((double)power)/(INT16_MAX * INT16_MAX)/in_frames; 206 info_valid = true; 207 QMutexLocker locker(&m_lock); 208 audioSamples.push_back(aSample); 209 } break; 210 case FORMAT_FLT: 211 { 212 double power = 0; 213 float *p = (float*)in_buffer; 214 for(f=in_frames;f>0;--f) 215 { 216 // power as mono 217 int64_t sum = 0; 218 for(i=settings.channels; i>0; --i) 219 { 220 sum += *p++; 221 p++; 222 } 223 power += sum * sum; 224 } 225 aSample->power += power/in_frames; 226 info_valid = true; 227 QMutexLocker locker(&m_lock); 228 audioSamples.push_back(aSample); 229 } break; 230 default: 231 break; 232 } 233 #ifdef AUDIODEBUGGING 234 if (info_valid) 235 { 236 LOG(VB_COMMFLAG, LOG_DEBUG, 237 QString("Audio AddData time %1 frames %2 power %3 changed %4").arg(timecode).arg(in_frames).arg(aSample->power).arg(aSample->changed)); 238 } 239 else 240 { 241 LOG(VB_COMMFLAG, LOG_DEBUG, 242 QString("Audio AddData time %1 frames %2").arg(timecode).arg(in_frames)); 243 } 244 #endif 245 last_audiotime = timecode; 246 return true; 247 } 248 249 const PAudioSample AudioBuffer::GetSample(int64_t time) const 250 { 251 if (audioSamples.size() > 0) 252 { 253 QMutexLocker locker(&m_lock); 254 int64_t index = (time - audioSamples[0]->time)/audioSamples[0]->duration; 255 //LOG(VB_COMMFLAG, LOG_DEBUG, QString("Audio GetSample time %1 tine0 %2 duration %3 index %4 size %5").arg(time).arg(audioSamples[0].time).arg(audioSamples[0].duration).arg(index).arg(audioSamples.size())); 256 if (index >= 0 && index < audioSamples.size()) 257 return audioSamples[index]; 258 } 259 return PAudioSample(); 260 } 261 262 void AudioBuffer::SetTimecode(int64_t timecode) 263 { 264 last_audiotime = timecode; 265 } 266 bool AudioBuffer::GetPause(void) 267 { 268 return false; 269 } 270 void AudioBuffer::Pause(bool paused) 271 { 272 (void)paused; 273 } 274 void AudioBuffer::Drain(void) 275 { 276 // Do nothing 277 return; 278 } 279 bool AudioBuffer::IsPaused() const { return false; } 280 void AudioBuffer::PauseUntilBuffered() { } 281 bool AudioBuffer::IsUpmixing() { return false; } 282 bool AudioBuffer::ToggleUpmix() { return false; } 283 bool AudioBuffer::CanUpmix() { return false; } 284 285 286 int64_t AudioBuffer::GetAudiotime(void) 287 { 288 return last_audiotime; 289 } 290 291 int AudioBuffer::GetVolumeChannel(int) const 292 { 293 // Do nothing 294 return 100; 295 } 296 void AudioBuffer::SetVolumeChannel(int, int) 297 { 298 // Do nothing 299 } 300 void AudioBuffer::SetVolumeAll(int) 301 { 302 // Do nothing 303 } 304 int AudioBuffer::GetSWVolume(void) 305 { 306 return 100; 307 } 308 void AudioBuffer::SetSWVolume(int, bool) {} 309 310 311 int AudioBuffer::GetCurrentVolume(void) 312 { 313 // Do nothing 314 return 100; 315 } 316 void AudioBuffer::SetCurrentVolume(int) 317 { 318 // Do nothing 319 } 320 void AudioBuffer::AdjustCurrentVolume(int) 321 { 322 // Do nothing 323 } 324 void AudioBuffer::SetMute(bool) 325 { 326 // Do nothing 327 } 328 void AudioBuffer::ToggleMute(void) 329 { 330 // Do nothing 331 } 332 MuteState AudioBuffer::GetMute(void) 333 { 334 // Do nothing 335 return kMuteOff; 336 } 337 MuteState AudioBuffer::IterateMutedChannels(void) 338 { 339 // Do nothing 340 return kMuteOff; 341 } 342 343 // These are pure virtual in AudioOutput, but we don't need them here 344 void AudioBuffer::bufferOutputData(bool){ return; } 345 int AudioBuffer::readOutputData(unsigned char*, int ){ return 0; } 346 347 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
new file mythtv/programs/mythcommflag/AudioBuffer.h
diff --git a/mythtv/programs/mythcommflag/AudioBuffer.h b/mythtv/programs/mythcommflag/AudioBuffer.h new file mode 100644 index 0000000..3c48f20
- + 1 #ifndef _AUDIOBUFFER_H_ 2 #define _AUDIOBUFFER_H_ 3 4 // POSIX headers 5 #include <stdint.h> 6 7 // Qt headers 8 #include <QObject> 9 #include <QSharedPointer> 10 11 // MythTV headers 12 #include "mythcontext.h" 13 14 #include "audiooutput.h" 15 16 #define COMM_DETECT_AUDIO 0x08 17 #define COMM_DETECT_2_AUDIO (COMM_DETECT_2 | COMM_DETECT_AUDIO) 18 19 //#define AUDIODEBUGGING 20 21 class AudioSample : public QSharedData 22 { 23 public: 24 int64_t time; 25 int64_t duration; 26 double power; 27 int channels; 28 bool changed; 29 AudioSample(); 30 QString toString() const; 31 }; 32 33 typedef QSharedDataPointer< AudioSample > PAudioSample; 34 35 36 #define CHANNELS_MIN 1 37 #define CHANNELS_MAX 8 38 class AudioBuffer : public AudioOutput 39 { 40 public: 41 AudioBuffer(const AudioSettings &settings); 42 ~AudioBuffer(); 43 44 AudioOutputSettings* GetOutputSettings(bool /*digital*/); 45 AudioOutputSettings* GetOutputSettingsUsers(bool digital); 46 AudioOutputSettings* GetOutputSettingsCleaned(bool digital); 47 48 // reconfigure sound out for new params 49 virtual void Reconfigure(const AudioSettings &orig_settings); 50 51 void Enable(); 52 53 virtual void SetEffDsp(int /* dsprate */); 54 virtual void SetBlocking(bool block); 55 virtual void Reset(void); 56 virtual bool AddFrames(void *in_buffer, int in_frames, int64_t timecode); 57 virtual bool AddData(void *in_buffer, int in_len, 58 int64_t timecode, int in_frames); 59 const PAudioSample GetSample(int64_t time) const; 60 virtual void SetTimecode(int64_t timecode); 61 virtual bool GetPause(void); 62 virtual void Pause(bool paused); 63 virtual void Drain(void); 64 virtual bool IsPaused() const; 65 virtual void PauseUntilBuffered(); 66 virtual bool IsUpmixing(); 67 virtual bool ToggleUpmix(); 68 virtual bool CanUpmix(); 69 70 virtual int64_t GetAudiotime(void); 71 virtual int GetVolumeChannel(int) const; 72 virtual void SetVolumeChannel(int, int); 73 virtual void SetVolumeAll(int); 74 virtual int GetSWVolume(void); 75 virtual void SetSWVolume(int, bool); 76 virtual int GetCurrentVolume(void); 77 virtual void SetCurrentVolume(int); 78 virtual void AdjustCurrentVolume(int); 79 virtual void SetMute(bool); 80 virtual void ToggleMute(void); 81 virtual MuteState GetMute(void); 82 virtual MuteState IterateMutedChannels(void); 83 84 // These are pure virtual in AudioOutput, but we don't need them here 85 virtual void bufferOutputData(bool); 86 virtual int readOutputData(unsigned char*, int ); 87 88 // Basic details about the audio stream 89 int channels; 90 int codec; 91 int bytes_per_frame; 92 int output_bytes_per_frame; 93 AudioFormat format; 94 AudioFormat output_format; 95 int samplerate; 96 int source_channels; 97 int source_samplerate; 98 int source_bytes_per_frame; 99 100 int bufsize; 101 //unsigned char *audiobuffer; 102 //int audiobuffer_len; 103 //int channels, bits, bytes_per_sample, eff_audiorate; 104 int configured_channels; 105 AudioSettings settings; 106 int64_t last_audiotime; 107 108 AudioOutputSettings* output_settings; 109 110 bool changed; 111 bool info_valid; 112 113 int64_t first_audiotime; 114 115 vector< PAudioSample > audioSamples; 116 117 private: 118 mutable QMutex m_lock; 119 bool verboseDebugging; 120 bool enabled; 121 }; 122 123 #endif 124 125 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
new file mythtv/programs/mythcommflag/AudioChangeDetector.cpp
diff --git a/mythtv/programs/mythcommflag/AudioChangeDetector.cpp b/mythtv/programs/mythcommflag/AudioChangeDetector.cpp new file mode 100644 index 0000000..63c8901
- + 1 using namespace std; 2 3 #include "AudioChangeDetector.h" 4 5 AudioChangeDetector::AudioChangeDetector() 6 { 7 } 8 9 void AudioChangeDetector::processFrame(unsigned char *frame) 10 { 11 } 12 13 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
new file mythtv/programs/mythcommflag/AudioChangeDetector.h
diff --git a/mythtv/programs/mythcommflag/AudioChangeDetector.h b/mythtv/programs/mythcommflag/AudioChangeDetector.h new file mode 100644 index 0000000..4d24215
- + 1 /* 2 * AudioChangeDetector 3 * 4 * Detect audi changes 5 */ 6 7 #ifndef __AUDIOCHANGEDETECTOR_H__ 8 #define __AUDIOCHANGEDETECTOR_H__ 9 10 #include "AudioChangeDetectorBase.h" 11 12 class AudioChangeDetector : public AudioChangeDetectorBase 13 { 14 public: 15 AudioChangeDetector(); 16 virtual ~AudioChangeDetector() {} 17 18 void processFrame(unsigned char *frame); 19 20 }; 21 22 #endif /* !__AUDIOCHANGEDETECTOR_H__ */ 23 24 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
new file mythtv/programs/mythcommflag/AudioChangeDetectorBase.cpp
diff --git a/mythtv/programs/mythcommflag/AudioChangeDetectorBase.cpp b/mythtv/programs/mythcommflag/AudioChangeDetectorBase.cpp new file mode 100644 index 0000000..a4dd42d
- + 1 2 #include "AudioChangeDetectorBase.h" 3 4 AudioChangeDetectorBase::AudioChangeDetectorBase() 5 { 6 } 7 8 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
new file mythtv/programs/mythcommflag/AudioChangeDetectorBase.h
diff --git a/mythtv/programs/mythcommflag/AudioChangeDetectorBase.h b/mythtv/programs/mythcommflag/AudioChangeDetectorBase.h new file mode 100644 index 0000000..7966869
- + 1 #ifndef _AUDIOCHANGEDETECTORBASE_H_ 2 #define _AUDIOCHANGEDETECTORBASE_H_ 3 4 #include <QObject> 5 6 class AudioChangeDetectorBase : public QObject 7 { 8 Q_OBJECT 9 10 public: 11 AudioChangeDetectorBase(); 12 13 virtual void processFrame(unsigned char *frame) = 0; 14 15 signals: 16 void haveNewInformation(unsigned int framenum, bool audiochange, 17 float amplitude, 18 float debugValue = 0.0); 19 20 protected: 21 virtual ~AudioChangeDetectorBase() {} 22 23 }; 24 25 #endif 26 27 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
mythtv/programs/mythcommflag/ClassicCommDetector.cpp
diff --git a/mythtv/programs/mythcommflag/ClassicCommDetector.cpp b/mythtv/programs/mythcommflag/ClassicCommDetector.cpp index c5c40fc..061bc23 100644
a b using namespace std; 20 20 21 21 // Commercial Flagging headers 22 22 #include "ClassicCommDetector.h" 23 #ifdef USEAUDIO 24 #include "AudioChangeDetector.h" 25 #endif 23 26 #include "ClassicLogoDetector.h" 24 27 #include "ClassicSceneChangeDetector.h" 28 #include "AudioBuffer.h" 25 29 26 30 enum frameAspects { 27 31 COMM_ASPECT_NORMAL = 0, … … static QString toStringFrameMaskValues(int mask, bool verbose) 53 57 msg += "aspect,"; 54 58 if (COMM_FRAME_RATING_SYMBOL & mask) 55 59 msg += "rating,"; 60 #ifdef USEAUDIO 61 if (COMM_FRAME_NO_AUDIO & mask) 62 msg += "silent,"; 63 if (COMM_FRAME_AUDIO_CHANGE & mask) 64 msg += "audchg,"; 65 if (COMM_FRAME_INVALID_AUDIO & mask) 66 msg += "noaud,"; 67 #endif 56 68 57 69 if (msg.length()) 58 70 msg = msg.left(msg.length() - 1); … … static QString toStringFrameMaskValues(int mask, bool verbose) 67 79 msg += (COMM_FRAME_LOGO_PRESENT & mask) ? "L" : " "; 68 80 msg += (COMM_FRAME_ASPECT_CHANGE & mask) ? "A" : " "; 69 81 msg += (COMM_FRAME_RATING_SYMBOL & mask) ? "R" : " "; 82 #ifdef USEAUDIO 83 msg += (COMM_FRAME_NO_AUDIO & mask) ? "Q" : " "; 84 msg += (COMM_FRAME_AUDIO_CHANGE & mask) ? "C" : " "; 85 msg += (COMM_FRAME_INVALID_AUDIO & mask) ? "I" : " "; 86 #endif 70 87 } 71 88 72 89 return msg; … … static QString toStringFrameFormats(int format, bool verbose) 99 116 100 117 QString FrameInfoEntry::GetHeader(void) 101 118 { 102 return QString(" frame min/max/avg scene aspect format flags");119 return QString(" frame min/max/avg scene aspect format apwr achan flags"); 103 120 } 104 121 105 122 QString FrameInfoEntry::toString(uint64_t frame, bool verbose) const 106 123 { 107 124 return QString( 125 #ifdef USEAUDIO 126 "%1: %2/%3/%4 %5% %6 %7 %8 %9 %10") 127 #else 108 128 "%1: %2/%3/%4 %5% %6 %7 %8") 129 #endif 109 130 .arg(frame,10) 110 131 .arg(minBrightness,3) 111 132 .arg(maxBrightness,3) … … QString FrameInfoEntry::toString(uint64_t frame, bool verbose) const 113 134 .arg(sceneChangePercent,3) 114 135 .arg(toStringFrameAspects(aspect, verbose)) 115 136 .arg(toStringFrameFormats(format, verbose)) 137 #ifdef USEAUDIO 138 .arg(audioPower,8) 139 .arg(audioMode,6) 140 #endif 116 141 .arg(toStringFrameMaskValues(flagMask, verbose)); 117 142 } 118 143 … … ClassicCommDetector::ClassicCommDetector(SkipType commDetectMethod_in, 134 159 horizSpacing(0), vertSpacing(0), 135 160 fpm(0.0), blankFramesOnly(false), 136 161 blankFrameCount(0), currentAspect(0), 162 silentFrameCount(0), 137 163 totalMinBrightness(0), detectBlankFrames(false), 138 164 detectSceneChanges(false), detectStationLogo(false), 165 detectSilentFrames(false), 139 166 logoInfoAvailable(false), logoDetector(0), 140 167 framePtr(0), frameIsBlank(false), 141 168 sceneHasChanged(false), stationLogoPresent(false), 142 169 lastFrameWasBlank(false), lastFrameWasSceneChange(false), 143 170 decoderFoundAspectChanges(false), sceneChangeDetector(0), 171 #if USEAUDIO 172 audioChangeDetector(0), 173 #endif 144 174 player(player_in), 145 175 startedAt(startedAt_in), stopsAt(stopsAt_in), 146 176 recordingStartedAt(recordingStartedAt_in), … … ClassicCommDetector::ClassicCommDetector(SkipType commDetectMethod_in, 170 200 gCoreContext->GetNumSetting("CommDetectMinShowLength", 65); 171 201 commDetectMaxCommLength = 172 202 gCoreContext->GetNumSetting("CommDetectMaxCommLength", 125); 203 commDetectLargeSceneChangeThreshold = 204 gCoreContext->GetNumSetting("CommDetectLargeSceneChangeThreshold", 50); 205 QStringList commDetectCommLengthsString = 206 gCoreContext->GetSetting("CommDetectCommLengths", "15,20,30,40,60").split(',', QString::SkipEmptyParts); 207 for (QStringList::iterator it = commDetectCommLengthsString.begin(); it != commDetectCommLengthsString.end(); ++it) 208 commDetectCommLengths.append((*it).toFloat()); 173 209 174 210 commDetectBlankCanHaveLogo = 175 211 !!gCoreContext->GetNumSetting("CommDetectBlankCanHaveLogo", 1); 212 #ifdef USEAUDIO 213 AudioSettings settings("", ""); 214 AudioOutput *audioOutput = new AudioBuffer(settings); 215 audioBuffer = ((AudioBuffer*)audioOutput); 216 player->GetAudio()->SetAudioOutput(audioOutput); 217 #endif 218 176 219 } 177 220 178 221 void ClassicCommDetector::Init() … … void ClassicCommDetector::Init() 257 300 this, 258 301 SLOT(sceneChangeDetectorHasNewInformation(unsigned int,bool,float)) 259 302 ); 303 #ifdef USEAUDIO 304 silentFrameCount = 0; 305 audioChangeDetector = new AudioChangeDetector(); 306 connect( 307 audioChangeDetector, 308 SIGNAL(haveNewInformation(unsigned int,bool,float,float)), 309 this, 310 SLOT(audioDetectorHasNewInformation(unsigned int,bool,float,float)) 311 ); 312 #endif 260 313 261 314 frameIsBlank = false; 262 315 stationLogoPresent = false; … … void ClassicCommDetector::Init() 278 331 279 332 void ClassicCommDetector::deleteLater(void) 280 333 { 334 #ifdef USEAUDIO 335 if (audioBuffer) 336 { 337 if (player && player->GetAudio()) 338 player->GetAudio()->SetAudioOutput(NULL); 339 delete audioBuffer; 340 audioBuffer = NULL; 341 } 342 #endif 281 343 if (sceneChangeDetector) 282 344 sceneChangeDetector->deleteLater(); 283 345 … … void ClassicCommDetector::deleteLater(void) 289 351 290 352 bool ClassicCommDetector::go() 291 353 { 354 #ifdef USEAUDIO 355 player->GetAudio()->ReinitAudio(); 356 #endif 292 357 int secsSince = 0; 293 358 int requiredBuffer = 30; 294 359 int requiredHeadStart = requiredBuffer; … … bool ClassicCommDetector::go() 401 466 402 467 emit breathe(); 403 468 469 audioBuffer->Enable(); 470 471 // make sure we get a key frame before us otherwise reset doesnt happen correctly. 472 player->DiscardVideoFrame(player->GetRawVideoFrame(60)); 473 474 emit breathe(); 475 476 player->DiscardVideoFrame(player->GetRawVideoFrame(0)); 404 477 player->ResetTotalDuration(); 405 478 406 479 while (!player->GetEof()) … … void ClassicCommDetector::sceneChangeDetectorHasNewInformation( 606 679 } 607 680 608 681 frameInfo[framenum].sceneChangePercent = (int) (debugValue*100); 682 683 if (verboseDebugging) 684 { 685 //LOG(VB_COMMFLAG, LOG_DEBUG, QString("Scene Change @%1 : %2 %3").arg(framenum).arg(isSceneChange).arg((int)(debugValue*100))); 686 } 609 687 } 610 688 689 #ifdef USEAUDIO 690 void ClassicCommDetector::audioDetectorHasNewInformation( 691 unsigned int framenum, bool hasChanged, float amplitude, float debugValue) 692 { 693 if (hasChanged) 694 frameInfo[framenum].flagMask |= COMM_FRAME_AUDIO_CHANGE; 695 else 696 frameInfo[framenum].flagMask &= ~COMM_FRAME_AUDIO_CHANGE; 697 frameInfo[framenum].audioMode = (int) (debugValue); 698 } 699 #endif 700 611 701 void ClassicCommDetector::GetCommercialBreakList(frm_dir_map_t &marks) 612 702 { 613 703 … … void ClassicCommDetector::GetCommercialBreakList(frm_dir_map_t &marks) 620 710 bool blank = COMM_DETECT_BLANK & commDetectMethod; 621 711 bool scene = COMM_DETECT_SCENE & commDetectMethod; 622 712 bool logo = COMM_DETECT_LOGO & commDetectMethod; 713 bool audio = COMM_DETECT_AUDIO & commDetectMethod; 623 714 624 715 if (COMM_DETECT_OFF == commDetectMethod) 625 716 return; 626 717 627 if (!blank && !scene && !logo )718 if (!blank && !scene && !logo && !audio) 628 719 { 629 720 LOG(VB_COMMFLAG, LOG_ERR, QString("Unexpected commDetectMethod: 0x%1") 630 721 .arg(commDetectMethod,0,16)); … … void ClassicCommDetector::GetCommercialBreakList(frm_dir_map_t &marks) 657 748 marks = logoCommBreakMap; 658 749 } 659 750 660 int cnt = ((blank) ? 1 : 0) + ((scene) ? 1 : 0) + ((logo) ? 1 : 0); 661 if (cnt == 2) 751 if (audio) 752 { 753 BuildAudioFrameCommList(); 754 marks = audioCommBreakMap; 755 } 756 757 int cnt = ((blank) ? 1 : 0) + ((scene) ? 1 : 0) + ((logo) ? 1 : 0) + ((audio) ? 1 : 0); 758 if (cnt >= 2) 662 759 { 663 if (blank && scene) 760 marks.clear(); 761 if (blank) 762 { 763 marks = Combine2Maps(blankCommBreakMap, marks); 764 } 765 if (scene) 664 766 { 665 marks = commBreakMap = Combine2Maps( 666 blankCommBreakMap, sceneCommBreakMap); 767 marks = Combine2Maps(sceneCommBreakMap, marks); 667 768 } 668 else if (blank &&logo)769 if (logo) 669 770 { 670 marks = commBreakMap = Combine2Maps( 671 blankCommBreakMap, logoCommBreakMap); 771 marks = Combine2Maps(logoCommBreakMap, marks); 672 772 } 673 else if (scene && logo)773 if (audio) 674 774 { 675 marks = commBreakMap = Combine2Maps( 676 sceneCommBreakMap, logoCommBreakMap); 775 marks = Combine2Maps(audioCommBreakMap, marks); 677 776 } 777 commBreakMap = marks; 678 778 } 679 779 680 780 LOG(VB_COMMFLAG, LOG_INFO, "Final Commercial Break Map"); … … void ClassicCommDetector::ProcessFrame(VideoFrame *frame, 807 907 808 908 if (commDetectMethod & COMM_DETECT_SCENE) 809 909 { 810 sceneChangeDetector->processFrame(framePtr );910 sceneChangeDetector->processFrame(framePtr, curFrameNumber); 811 911 } 812 912 813 913 stationLogoPresent = false; … … void ClassicCommDetector::ProcessFrame(VideoFrame *frame, 958 1058 if (stationLogoPresent) 959 1059 flagMask |= COMM_FRAME_LOGO_PRESENT; 960 1060 1061 #ifdef USEAUDIO 1062 if (commDetectMethod & COMM_DETECT_AUDIO) 1063 { 1064 if (audioBuffer) 1065 { 1066 // process a number of frames worth of audio 1067 const AudioSample* audSample = audioBuffer->GetSample(frame->timecode); 1068 int loops = 1000; 1069 do 1070 { 1071 usleep(1000); 1072 emit breathe(); 1073 audSample = audioBuffer->GetSample(frame->timecode); 1074 if (--loops == 0) 1075 break; 1076 } 1077 while (audSample == NULL); 1078 1079 if (audSample && (audSample->power >= 0)) 1080 { 1081 frameInfo[curFrameNumber].audioPower = audSample->power; 1082 frameInfo[curFrameNumber].audioMode = audSample->channels; 1083 if (audSample->changed) 1084 flagMask |= COMM_FRAME_AUDIO_CHANGE; 1085 if (audSample->power < 1e-6) 1086 { 1087 flagMask |= COMM_FRAME_NO_AUDIO; 1088 silentFrameCount++; 1089 } 1090 #ifdef AUDIODEBUGGING 1091 if (verboseDebugging) 1092 { 1093 LOG(VB_COMMFLAG, LOG_DEBUG, QString(" video %1 audio %3") 1094 .arg(frame->timecode) 1095 .arg(audSample->toString())); 1096 } 1097 #endif 1098 } 1099 else 1100 { 1101 #ifdef AUDIODEBUGGING 1102 if (verboseDebugging) 1103 { 1104 LOG(VB_COMMFLAG, LOG_DEBUG, QString(" video %1") 1105 .arg(frame->timecode)); 1106 } 1107 #endif 1108 frameInfo[curFrameNumber].audioPower = 0; 1109 flagMask |= COMM_FRAME_INVALID_AUDIO; 1110 } 1111 } 1112 } 1113 #endif 1114 961 1115 //TODO: move this debugging code out of the perframe loop, and do it after 962 1116 // we've processed all frames. this is because a scenechangedetector can 963 1117 // now use a few frames to determine whether the frame a few frames ago was … … void ClassicCommDetector::ProcessFrame(VideoFrame *frame, 968 1122 969 1123 if (verboseDebugging) 970 1124 LOG(VB_COMMFLAG, LOG_DEBUG, 1125 #ifdef USEAUDIO 1126 QString().sprintf("Frame: %6ld -> %3d %3d %3d %3d %1d %1d %9.6f %1d %04x", 1127 #else 971 1128 QString().sprintf("Frame: %6ld -> %3d %3d %3d %3d %1d %1d %04x", 1129 #endif 972 1130 (long)curFrameNumber, 973 1131 frameInfo[curFrameNumber].minBrightness, 974 1132 frameInfo[curFrameNumber].maxBrightness, … … void ClassicCommDetector::ProcessFrame(VideoFrame *frame, 976 1134 frameInfo[curFrameNumber].sceneChangePercent, 977 1135 frameInfo[curFrameNumber].format, 978 1136 frameInfo[curFrameNumber].aspect, 1137 #ifdef USEAUDIO 1138 frameInfo[curFrameNumber].audioPower, 1139 frameInfo[curFrameNumber].audioMode, 1140 #endif 979 1141 frameInfo[curFrameNumber].flagMask )); 980 1142 981 1143 #ifdef SHOW_DEBUG_WIN … … void ClassicCommDetector::ClearAllMaps(void) 998 1160 blankCommBreakMap.clear(); 999 1161 sceneMap.clear(); 1000 1162 sceneCommBreakMap.clear(); 1163 audioCommBreakMap.clear(); 1001 1164 commBreakMap.clear(); 1002 1165 } 1003 1166 … … void ClassicCommDetector::GetBlankCommBreakMap(frm_dir_map_t &comms) 1021 1184 comms = blankCommBreakMap; 1022 1185 } 1023 1186 1187 void ClassicCommDetector::GetAudioCommBreakMap(frm_dir_map_t &comms) 1188 { 1189 LOG(VB_COMMFLAG, LOG_INFO, "CommDetect::GetAudioCommBreakMap()"); 1190 1191 if (audioCommBreakMap.isEmpty()) 1192 BuildAudioFrameCommList(); 1193 1194 comms = audioCommBreakMap; 1195 } 1196 1024 1197 void ClassicCommDetector::GetSceneChangeMap(frm_dir_map_t &scenes, 1025 1198 int64_t start_frame) 1026 1199 { … … void ClassicCommDetector::UpdateFrameBlock(FrameBlock *fbp, 1143 1316 1144 1317 value = finfo.flagMask; 1145 1318 1319 if (value & COMM_FRAME_BLANK) 1320 fbp->bfCount++; 1321 1146 1322 if (value & COMM_FRAME_LOGO_PRESENT) 1147 1323 fbp->logoCount++; 1148 1324 … … void ClassicCommDetector::UpdateFrameBlock(FrameBlock *fbp, 1152 1328 if (value & COMM_FRAME_SCENE_CHANGE) 1153 1329 fbp->scCount++; 1154 1330 1331 #ifdef USEAUDIO 1332 if (value & COMM_FRAME_NO_AUDIO) 1333 fbp->saCount++; 1334 1335 if (value & COMM_FRAME_AUDIO_CHANGE) 1336 fbp->acCount++; 1337 1338 fbp->aPowerAvg += finfo.audioPower; 1339 if (fbp->aPowerMin > finfo.audioPower) 1340 fbp->aPowerMin = finfo.audioPower; 1341 if (fbp->aPowerMax < finfo.audioPower) 1342 fbp->aPowerMax = finfo.audioPower; 1343 #endif 1344 1155 1345 if (finfo.format == format) 1156 1346 fbp->formatMatch++; 1157 1347 … … void ClassicCommDetector::BuildAllMethodsCommList(void) 1177 1367 uint64_t lastStart = 0; 1178 1368 uint64_t lastEnd = 0; 1179 1369 int64_t firstLogoFrame = -1; 1180 bool nextFrameIsBlank = false;1181 1370 bool lastFrameWasBlank = false; 1371 bool lastFrameWasSilent = false; 1182 1372 uint64_t formatFrames = 0; 1183 1373 int format = COMM_FORMAT_NORMAL; 1184 1374 uint64_t aspectFrames = 0; … … void ClassicCommDetector::BuildAllMethodsCommList(void) 1188 1378 frm_dir_map_t tmpCommMap; 1189 1379 frm_dir_map_t::iterator it; 1190 1380 1381 //bool preferAudioBreaks = (commDetectMethod & COMM_DETECT_AUDIO); 1382 1191 1383 commBreakMap.clear(); 1192 1384 1193 fblock = new FrameBlock[blankFrameCount + 2 ];1385 fblock = new FrameBlock[blankFrameCount + 2 + silentFrameCount + 2]; 1194 1386 1195 1387 curBlock = 0; 1196 1388 curFrame = 1; … … void ClassicCommDetector::BuildAllMethodsCommList(void) 1198 1390 fbp = &fblock[curBlock]; 1199 1391 fbp->start = 0; 1200 1392 fbp->bfCount = 0; 1393 fbp->saCount = 0; 1394 fbp->aPowerAvg = 0; 1395 fbp->aPowerMin = 1e40; 1396 fbp->aPowerMax = 0; 1397 fbp->acCount = 0; 1201 1398 fbp->logoCount = 0; 1202 1399 fbp->ratingCount = 0; 1203 1400 fbp->scCount = 0; … … void ClassicCommDetector::BuildAllMethodsCommList(void) 1207 1404 fbp->score = 0; 1208 1405 1209 1406 lastFrameWasBlank = true; 1407 lastFrameWasSilent = true; 1210 1408 1211 1409 if (decoderFoundAspectChanges) 1212 1410 { … … void ClassicCommDetector::BuildAllMethodsCommList(void) 1245 1443 } 1246 1444 } 1247 1445 1446 #define SPLIT_MODE 2 1248 1447 while (curFrame <= framesProcessed) 1249 1448 { 1250 1449 value = frameInfo[curFrame].flagMask; 1251 1450 1252 if (((curFrame + 1) <= framesProcessed) && 1253 (frameInfo[curFrame + 1].flagMask & COMM_FRAME_BLANK)) 1254 nextFrameIsBlank = true; 1255 else 1256 nextFrameIsBlank = false; 1451 bool newBlockMask = false; 1452 bool lastSilentFrameState = lastFrameWasSilent; 1453 lastFrameWasSilent = value & COMM_FRAME_NO_AUDIO; 1454 newBlockMask |= (lastSilentFrameState != lastFrameWasSilent); 1257 1455 1258 if (value & COMM_FRAME_BLANK) 1259 { 1260 fbp->bfCount++; 1261 1262 if (!nextFrameIsBlank || !lastFrameWasBlank) 1263 { 1264 UpdateFrameBlock(fbp, frameInfo[curFrame], format, aspect); 1265 1266 fbp->end = curFrame; 1267 fbp->frames = fbp->end - fbp->start + 1; 1268 fbp->length = fbp->frames / fps; 1269 1270 if ((fbp->scCount) && (fbp->length > 1.05)) 1271 fbp->scRate = fbp->scCount / fbp->length; 1272 1273 curBlock++; 1274 1275 fbp = &fblock[curBlock]; 1276 fbp->bfCount = 1; 1277 fbp->logoCount = 0; 1278 fbp->ratingCount = 0; 1279 fbp->scCount = 0; 1280 fbp->scRate = 0.0; 1281 fbp->score = 0; 1282 fbp->formatMatch = 0; 1283 fbp->aspectMatch = 0; 1284 fbp->start = curFrame; 1285 } 1456 bool lastBlankFrameState = lastFrameWasBlank; 1457 lastFrameWasBlank = value & COMM_FRAME_BLANK; 1458 #if SPLIT_MODE == 1 1459 newBlockMask |= (lastBlankFrameState != lastFrameWasBlank); 1460 #elif SPLIT_MODE == 2 1461 // transition only when both are set 1462 newBlockMask = (lastSilentFrameState & lastBlankFrameState) != (lastFrameWasSilent & lastFrameWasBlank); 1286 1463 1287 lastFrameWasBlank = true; 1288 } 1289 else 1464 if ((frameInfo[curFrame].sceneChangePercent < 50) && lastFrameWasSilent && !lastFrameWasBlank) 1290 1465 { 1291 lastFrameWasBlank = false;1466 newBlockMask |= true; 1292 1467 } 1468 #endif 1293 1469 1470 if (newBlockMask) 1471 { 1472 fbp->end = curFrame - 1; 1473 fbp->frames = fbp->end - fbp->start + 1; 1474 fbp->length = fbp->frames / fps; 1475 1476 fbp->aPowerAvg /= fbp->frames; 1477 1478 if ((fbp->scCount) && (fbp->length > 1.05)) 1479 fbp->scRate = fbp->scCount / fbp->length; 1480 1481 curBlock++; 1482 1483 fbp = &fblock[curBlock]; 1484 fbp->bfCount = 0; 1485 fbp->saCount = 0; 1486 fbp->acCount = 0; 1487 fbp->aPowerAvg = 0; 1488 fbp->aPowerMin = 1e40; 1489 fbp->aPowerMax = 0; 1490 fbp->logoCount = 0; 1491 fbp->ratingCount = 0; 1492 fbp->scCount = 0; 1493 fbp->scRate = 0.0; 1494 fbp->score = 0; 1495 fbp->formatMatch = 0; 1496 fbp->aspectMatch = 0; 1497 fbp->start = curFrame; 1498 } 1294 1499 UpdateFrameBlock(fbp, frameInfo[curFrame], format, aspect); 1295 1500 1296 1501 if ((value & COMM_FRAME_LOGO_PRESENT) && … … void ClassicCommDetector::BuildAllMethodsCommList(void) 1300 1505 curFrame++; 1301 1506 } 1302 1507 1303 fbp->end = curFrame ;1508 fbp->end = curFrame - 1; 1304 1509 fbp->frames = fbp->end - fbp->start + 1; 1305 1510 fbp->length = fbp->frames / fps; 1306 1511 1512 fbp->aPowerAvg /= fbp->frames; 1513 1307 1514 if ((fbp->scCount) && (fbp->length > 1.05)) 1308 1515 fbp->scRate = fbp->scCount / fbp->length; 1309 1516 … … void ClassicCommDetector::BuildAllMethodsCommList(void) 1314 1521 LOG(VB_COMMFLAG, LOG_INFO, "Initial Block pass"); 1315 1522 LOG(VB_COMMFLAG, LOG_DEBUG, 1316 1523 "Block StTime StFrm EndFrm Frames Secs " 1317 "Bf Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch S core");1524 "Bf Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch SA Cnt AC Cnt AudPower Score"); 1318 1525 LOG(VB_COMMFLAG, LOG_INFO, 1319 1526 "----- ------ ------ ------ ------ ------- " 1320 "--- ------ ------ ------ ----- ------ ------ ----- ");1527 "--- ------ ------ ------ ----- ------ ------ ------ -------- -----"); 1321 1528 while (curBlock <= maxBlock) 1322 1529 { 1323 1530 fbp = &fblock[curBlock]; 1324 1531 1325 1532 msg.sprintf("%5d %3d:%02d %6ld %6ld %6ld %7.2f %3d %6d %6d %6d " 1326 "%5.2f %6d %6d % 5d",1533 "%5.2f %6d %6d %6d %6d %8f %8f %8f %5d", 1327 1534 curBlock, (int)(fbp->start / fps) / 60, 1328 1535 (int)((fbp->start / fps )) % 60, 1329 1536 fbp->start, fbp->end, fbp->frames, fbp->length, 1330 1537 fbp->bfCount, fbp->logoCount, fbp->ratingCount, 1331 1538 fbp->scCount, fbp->scRate, fbp->formatMatch, 1332 fbp->aspectMatch, fbp->s core);1539 fbp->aspectMatch, fbp->saCount, fbp->acCount, fbp->aPowerAvg, fbp->aPowerMin, fbp->aPowerMax, fbp->score); 1333 1540 LOG(VB_COMMFLAG, LOG_DEBUG, msg); 1334 1541 1542 #if SPLIT_MODE == 1 1543 if ((fbp->saCount >= 2) && (fbp->bfCount >= 2)) 1544 { 1545 for(int i=0; i<5; i++) 1546 { 1547 if (curBlock+1 > maxBlock) 1548 break; 1549 FrameBlock *fbp2 = &fblock[curBlock + i]; 1550 if ((fbp2->saCount > 0) || (fbp2->bfCount > 0)) 1551 continue; 1552 if (fbp2->frames < fps) 1553 continue; 1554 if (fbp2->frames > commDetectMaxCommLength) 1555 { 1556 if (verboseDebugging) 1557 LOG(VB_COMMFLAG, LOG_DEBUG, 1558 QString(" blank+silent length @+%1 > max comm length, +10").arg(i)); 1559 fbp2->score += 10; 1560 } 1561 if (fbp2->frames > commDetectMaxCommBreakLength) 1562 { 1563 if (verboseDebugging) 1564 LOG(VB_COMMFLAG, LOG_DEBUG, 1565 QString(" blank+silent length @+%1 > max comm break length, +20").arg(i)); 1566 fbp2->score += 20; 1567 } 1568 break; 1569 } 1570 } 1571 #endif 1572 1335 1573 if (fbp->frames > fps) 1336 1574 { 1337 1575 if (verboseDebugging) … … void ClassicCommDetector::BuildAllMethodsCommList(void) 1379 1617 } 1380 1618 1381 1619 if ((logoInfoAvailable) && 1382 (fbp->logoCount < (fbp->frames * 0.50))) 1620 (fbp->logoCount < (fbp->frames * 0.50)) && 1621 (fbp->bfCount < (fbp->frames * 0.10))) 1383 1622 { 1384 1623 if (verboseDebugging) 1385 1624 LOG(VB_COMMFLAG, LOG_DEBUG, 1386 " logoInfoAvailable && logoCount < frames * .50 , "1625 " logoInfoAvailable && logoCount < frames * .50 && blanks < frames * 0.1, " 1387 1626 "-10"); 1388 1627 fbp->score -= 10; 1389 1628 } … … void ClassicCommDetector::BuildAllMethodsCommList(void) 1397 1636 } 1398 1637 1399 1638 if ((fbp->scRate > 1.0) && 1639 (fbp->bfCount < (fbp->frames * 0.50)) && 1400 1640 (fbp->logoCount < (fbp->frames * .90))) 1401 1641 { 1402 1642 if (verboseDebugging) … … void ClassicCommDetector::BuildAllMethodsCommList(void) 1421 1661 fbp->score -= 20; 1422 1662 } 1423 1663 1424 if ((abs((int)(fbp->frames - (15 * fps))) < 5 ) || 1425 (abs((int)(fbp->frames - (30 * fps))) < 6 ) || 1426 (abs((int)(fbp->frames - (60 * fps))) < 8 )) 1664 // check for common comm break lengths 1665 for(QList<float>::iterator lit = commDetectCommLengths.begin(); lit != commDetectCommLengths.end(); ++lit) 1427 1666 { 1428 if (verboseDebugging) 1429 LOG(VB_COMMFLAG, LOG_DEBUG, 1430 " block appears to be standard comm length, -10"); 1431 fbp->score -= 10; 1667 if (abs(fbp->frames - (*lit * fps) + fps/2) < (fps/2)) 1668 { 1669 if (verboseDebugging) 1670 LOG(VB_COMMFLAG, LOG_DEBUG, 1671 " block appears to be standard comm length, -10"); 1672 fbp->score -= 10; 1673 break; 1674 } 1432 1675 } 1433 1676 } 1434 1677 else … … void ClassicCommDetector::BuildAllMethodsCommList(void) 1476 1719 } 1477 1720 1478 1721 msg.sprintf(" NOW %3d:%02d %6ld %6ld %6ld %7.2f %3d %6d %6d %6d " 1479 "%5.2f %6d %6d % 5d",1722 "%5.2f %6d %6d %6d %6d %8f %8f %8f %5d", 1480 1723 (int)(fbp->start / fps) / 60, 1481 1724 (int)((fbp->start / fps )) % 60, 1482 1725 fbp->start, fbp->end, fbp->frames, fbp->length, 1483 1726 fbp->bfCount, fbp->logoCount, fbp->ratingCount, 1484 1727 fbp->scCount, fbp->scRate, fbp->formatMatch, 1485 fbp->aspectMatch, fbp->s core);1728 fbp->aspectMatch, fbp->saCount, fbp->acCount, fbp->aPowerAvg, fbp->aPowerMin, fbp->aPowerMax, fbp->score); 1486 1729 LOG(VB_COMMFLAG, LOG_DEBUG, msg); 1487 1730 1488 1731 lastScore = fbp->score; … … void ClassicCommDetector::BuildAllMethodsCommList(void) 1496 1739 LOG(VB_COMMFLAG, LOG_INFO, "Second Block pass"); 1497 1740 LOG(VB_COMMFLAG, LOG_DEBUG, 1498 1741 "Block StTime StFrm EndFrm Frames Secs " 1499 "Bf Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch S core");1742 "Bf Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch SA Cnt AC Cnt AudPower Score"); 1500 1743 LOG(VB_COMMFLAG, LOG_DEBUG, 1501 1744 "----- ------ ------ ------ ------ ------- " 1502 "--- ------ ------ ------ ----- ------ ------ ----- ");1745 "--- ------ ------ ------ ----- ------ ------ ------ ------ -------- -----"); 1503 1746 while (curBlock <= maxBlock) 1504 1747 { 1505 1748 fbp = &fblock[curBlock]; 1506 1749 1507 1750 msg.sprintf("%5d %3d:%02d %6ld %6ld %6ld %7.2f %3d %6d %6d %6d " 1508 "%5.2f %6d %6d % 5d",1751 "%5.2f %6d %6d %6d %6d %8f %8f %8f %5d", 1509 1752 curBlock, (int)(fbp->start / fps) / 60, 1510 1753 (int)((fbp->start / fps )) % 60, 1511 1754 fbp->start, fbp->end, fbp->frames, fbp->length, 1512 1755 fbp->bfCount, fbp->logoCount, fbp->ratingCount, 1513 1756 fbp->scCount, fbp->scRate, fbp->formatMatch, 1514 fbp->aspectMatch, fbp->s core);1757 fbp->aspectMatch, fbp->saCount, fbp->acCount, fbp->aPowerAvg, fbp->aPowerMin, fbp->aPowerMax, fbp->score); 1515 1758 LOG(VB_COMMFLAG, LOG_DEBUG, msg); 1516 1759 1517 1760 if ((curBlock > 0) && (curBlock < maxBlock)) … … void ClassicCommDetector::BuildAllMethodsCommList(void) 1537 1780 "lastScore < 0 && nextScore < 0, setting -10"); 1538 1781 fbp->score -= 10; 1539 1782 } 1783 if ((fbp->saCount > (fbp->frames * 0.95)) && 1784 (fbp->frames < (2*fps)) && 1785 (lastScore < 0 && nextScore < 0)) 1786 { 1787 if (verboseDebugging) 1788 LOG(VB_COMMFLAG, LOG_DEBUG, 1789 " silent > frames * 0.95 && frames < 2*fps && " 1790 "lastScore < 0 && nextScore < 0, setting -10"); 1791 fbp->score -= 10; 1792 } 1540 1793 1541 1794 if ((fbp->frames < (120*fps)) && 1542 1795 (lastScore < 0) && … … void ClassicCommDetector::BuildAllMethodsCommList(void) 1602 1855 } 1603 1856 1604 1857 msg.sprintf(" NOW %3d:%02d %6ld %6ld %6ld %7.2f %3d %6d %6d %6d " 1605 "%5.2f %6d %6d % 5d",1858 "%5.2f %6d %6d %6d %6d %8f %8f %8f %5d", 1606 1859 (int)(fbp->start / fps) / 60, 1607 1860 (int)((fbp->start / fps )) % 60, 1608 1861 fbp->start, fbp->end, fbp->frames, fbp->length, 1609 1862 fbp->bfCount, fbp->logoCount, fbp->ratingCount, 1610 1863 fbp->scCount, fbp->scRate, fbp->formatMatch, 1611 fbp->aspectMatch, fbp->s core);1864 fbp->aspectMatch, fbp->saCount, fbp->acCount, fbp->aPowerAvg, fbp->aPowerMin, fbp->aPowerMax, fbp->score); 1612 1865 LOG(VB_COMMFLAG, LOG_DEBUG, msg); 1613 1866 1614 1867 lastScore = fbp->score; … … void ClassicCommDetector::BuildAllMethodsCommList(void) 1619 1872 LOG(VB_COMMFLAG, LOG_INFO, "FINAL Block stats"); 1620 1873 LOG(VB_COMMFLAG, LOG_DEBUG, 1621 1874 "Block StTime StFrm EndFrm Frames Secs " 1622 "Bf Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch S core");1875 "Bf Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch SA Cnt AC Cnt AudPower Score"); 1623 1876 LOG(VB_COMMFLAG, LOG_DEBUG, 1624 1877 "----- ------ ------ ------ ------ ------- " 1625 "--- ------ ------ ------ ----- ------ ------ ----- ");1878 "--- ------ ------ ------ ----- ------ ------ ------ ------ -------- -----"); 1626 1879 curBlock = 0; 1627 1880 lastScore = 0; 1628 1881 breakStart = -1; … … void ClassicCommDetector::BuildAllMethodsCommList(void) 1780 2033 } 1781 2034 1782 2035 msg.sprintf("%5d %3d:%02d %6ld %6ld %6ld %7.2f %3d %6d %6d %6d " 1783 "%5.2f %6d %6d % 5d",2036 "%5.2f %6d %6d %6d %6d %8f %8f %8f %5d", 1784 2037 curBlock, (int)(fbp->start / fps) / 60, 1785 2038 (int)((fbp->start / fps )) % 60, 1786 2039 fbp->start, fbp->end, fbp->frames, fbp->length, 1787 2040 fbp->bfCount, fbp->logoCount, fbp->ratingCount, 1788 2041 fbp->scCount, fbp->scRate, fbp->formatMatch, 1789 fbp->aspectMatch, thisScore);2042 fbp->aspectMatch, fbp->saCount, fbp->acCount, fbp->aPowerAvg, fbp->aPowerMin, fbp->aPowerMax, thisScore); 1790 2043 LOG(VB_COMMFLAG, LOG_DEBUG, msg); 1791 2044 1792 2045 lastScore = thisScore; … … void ClassicCommDetector::BuildBlankFrameCommList(void) 2033 2286 .arg(it.key()).arg(*it)); 2034 2287 } 2035 2288 2289 void ClassicCommDetector::BuildAudioFrameCommList(void) 2290 { 2291 LOG(VB_COMMFLAG, LOG_INFO, "CommDetect::BuildBlankFrameCommList()"); 2292 2293 audioCommBreakMap.clear(); 2294 // TODO 2295 } 2036 2296 2037 2297 void ClassicCommDetector::BuildSceneChangeCommList(void) 2038 2298 { -
mythtv/programs/mythcommflag/ClassicCommDetector.h
diff --git a/mythtv/programs/mythcommflag/ClassicCommDetector.h b/mythtv/programs/mythcommflag/ClassicCommDetector.h index f9e5c4c..adcfd32 100644
a b class MythPlayer; 20 20 class LogoDetectorBase; 21 21 class SceneChangeDetectorBase; 22 22 23 #ifdef USEAUDIO 24 class AudioChangeDetectorBase; 25 class AudioBuffer; 26 #endif 27 23 28 enum frameMaskValues { 24 29 COMM_FRAME_SKIPPED = 0x0001, 25 30 COMM_FRAME_BLANK = 0x0002, … … enum frameMaskValues { 27 32 COMM_FRAME_LOGO_PRESENT = 0x0008, 28 33 COMM_FRAME_ASPECT_CHANGE = 0x0010, 29 34 COMM_FRAME_RATING_SYMBOL = 0x0020 35 #ifdef USEAUDIO 36 ,COMM_FRAME_NO_AUDIO = 0x0100 37 ,COMM_FRAME_AUDIO_CHANGE = 0x0200 38 ,COMM_FRAME_INVALID_AUDIO = 0x0400 39 #endif 30 40 }; 31 41 32 42 class FrameInfoEntry … … class FrameInfoEntry 38 48 int sceneChangePercent; 39 49 int aspect; 40 50 int format; 51 #ifdef USEAUDIO 52 double audioPower; 53 int audioMode; 54 #endif 41 55 int flagMask; 42 56 static QString GetHeader(void); 43 57 QString toString(uint64_t frame, bool verbose) const; … … class ClassicCommDetector : public CommDetectorBase 80 94 long frames; 81 95 double length; 82 96 int bfCount; 97 int saCount; 98 int acCount; 99 double aPowerAvg; 100 double aPowerMin; 101 double aPowerMax; 83 102 int logoCount; 84 103 int ratingCount; 85 104 int scCount; … … class ClassicCommDetector : public CommDetectorBase 93 112 void ClearAllMaps(void); 94 113 void GetBlankCommMap(frm_dir_map_t &comms); 95 114 void GetBlankCommBreakMap(frm_dir_map_t &comms); 115 void GetSilentCommMap(frm_dir_map_t &comms); 116 void GetAudioCommBreakMap(frm_dir_map_t &comms); 96 117 void GetSceneChangeMap(frm_dir_map_t &scenes, 97 118 int64_t start_frame); 98 119 frm_dir_map_t Combine2Maps( … … class ClassicCommDetector : public CommDetectorBase 101 122 int format, int aspect); 102 123 void BuildAllMethodsCommList(void); 103 124 void BuildBlankFrameCommList(void); 125 void BuildAudioFrameCommList(void); 104 126 void BuildSceneChangeCommList(void); 105 127 void BuildLogoCommList(); 106 128 void MergeBlankCommList(void); … … class ClassicCommDetector : public CommDetectorBase 128 150 int commDetectMinShowLength; 129 151 int commDetectMaxCommLength; 130 152 bool commDetectBlankCanHaveLogo; 153 int commDetectLargeSceneChangeThreshold; 154 QList<float> commDetectCommLengths; 131 155 132 156 bool verboseDebugging; 133 157 … … class ClassicCommDetector : public CommDetectorBase 142 166 bool blankFramesOnly; 143 167 int blankFrameCount; 144 168 int currentAspect; 169 int silentFrameCount; 145 170 146 171 147 172 int totalMinBrightness; … … class ClassicCommDetector : public CommDetectorBase 149 174 bool detectBlankFrames; 150 175 bool detectSceneChanges; 151 176 bool detectStationLogo; 177 bool detectSilentFrames; 152 178 153 179 bool logoInfoAvailable; 154 180 LogoDetectorBase* logoDetector; … … class ClassicCommDetector : public CommDetectorBase 158 184 frm_dir_map_t blankFrameMap; 159 185 frm_dir_map_t blankCommMap; 160 186 frm_dir_map_t blankCommBreakMap; 187 frm_dir_map_t silentFrameMap; 188 frm_dir_map_t audioCommBreakMap; 161 189 frm_dir_map_t sceneMap; 162 190 frm_dir_map_t sceneCommBreakMap; 163 191 frm_dir_map_t commBreakMap; … … class ClassicCommDetector : public CommDetectorBase 172 200 bool decoderFoundAspectChanges; 173 201 174 202 SceneChangeDetectorBase* sceneChangeDetector; 203 #if USEAUDIO 204 AudioChangeDetectorBase* audioChangeDetector; 205 #endif 175 206 176 207 protected: 177 208 MythPlayer *player; … … protected: 191 222 void SetVideoParams(float aspect); 192 223 void ProcessFrame(VideoFrame *frame, long long frame_number); 193 224 QMap<long long, FrameInfoEntry> frameInfo; 225 #ifdef USEAUDIO 226 AudioBuffer *audioBuffer; 227 int64_t audioFrame; 228 #endif 194 229 195 230 public slots: 196 231 void sceneChangeDetectorHasNewInformation(unsigned int framenum, bool isSceneChange,float debugValue); 232 #ifdef USEAUDIO 233 void audioDetectorHasNewInformation(unsigned int framenum, bool hasChanged, float amplitude, float debugValue); 234 #endif 197 235 }; 198 236 199 237 #endif -
mythtv/programs/mythcommflag/ClassicSceneChangeDetector.cpp
diff --git a/mythtv/programs/mythcommflag/ClassicSceneChangeDetector.cpp b/mythtv/programs/mythcommflag/ClassicSceneChangeDetector.cpp index c449353..a626061 100644
a b 1 1 #include <algorithm> 2 2 using namespace std; 3 3 4 // MythTV headers 5 #include "mythcontext.h" 6 4 7 #include "ClassicSceneChangeDetector.h" 5 8 #include "Histogram.h" 6 9 … … ClassicSceneChangeDetector::ClassicSceneChangeDetector(unsigned int width, 16 19 { 17 20 histogram = new Histogram; 18 21 previousHistogram = new Histogram; 22 commDetectSceneChangeThreshold = 23 gCoreContext->GetNumSetting("CommDetectSceneChangeThreshold", 60)/100.0; 19 24 } 20 25 21 26 void ClassicSceneChangeDetector::deleteLater(void) … … void ClassicSceneChangeDetector::deleteLater(void) 25 30 SceneChangeDetectorBase::deleteLater(); 26 31 } 27 32 28 void ClassicSceneChangeDetector::processFrame(unsigned char* frame )33 void ClassicSceneChangeDetector::processFrame(unsigned char* frame, long long frameNumber) 29 34 { 30 35 histogram->generateFromImage(frame, width, height, commdetectborder, 31 36 width-commdetectborder, commdetectborder, 32 37 height-commdetectborder, xspacing, yspacing); 33 38 float similar = histogram->calculateSimilarityWith(*previousHistogram); 34 39 35 bool isSceneChange = (similar < .85&& !previousFrameWasSceneChange);40 bool isSceneChange = (similar < commDetectSceneChangeThreshold && !previousFrameWasSceneChange); 36 41 37 42 emit(haveNewInformation(frameNumber,isSceneChange,similar)); 38 43 previousFrameWasSceneChange = isSceneChange; -
mythtv/programs/mythcommflag/ClassicSceneChangeDetector.h
diff --git a/mythtv/programs/mythcommflag/ClassicSceneChangeDetector.h b/mythtv/programs/mythcommflag/ClassicSceneChangeDetector.h index f4d2200..81b0127 100644
a b class ClassicSceneChangeDetector : public SceneChangeDetectorBase 13 13 unsigned int yspacing); 14 14 virtual void deleteLater(void); 15 15 16 void processFrame(unsigned char* frame );16 void processFrame(unsigned char* frame, long long frameNumber); 17 17 18 18 private: 19 19 ~ClassicSceneChangeDetector() {} … … class ClassicSceneChangeDetector : public SceneChangeDetectorBase 25 25 bool previousFrameWasSceneChange; 26 26 unsigned int xspacing, yspacing; 27 27 unsigned int commdetectborder; 28 double commDetectSceneChangeThreshold; 28 29 }; 29 30 30 31 #endif -
mythtv/programs/mythcommflag/SceneChangeDetectorBase.h
diff --git a/mythtv/programs/mythcommflag/SceneChangeDetectorBase.h b/mythtv/programs/mythcommflag/SceneChangeDetectorBase.h index 67296d5..f901407 100644
a b class SceneChangeDetectorBase : public QObject 11 11 SceneChangeDetectorBase(unsigned int w, unsigned int h) : 12 12 width(w), height(h) {} 13 13 14 virtual void processFrame(unsigned char *frame ) = 0;14 virtual void processFrame(unsigned char *frame, long long frameNumber) = 0; 15 15 16 16 signals: 17 17 void haveNewInformation(unsigned int framenum, bool scenechange, -
mythtv/programs/mythcommflag/main.cpp
diff --git a/mythtv/programs/mythcommflag/main.cpp b/mythtv/programs/mythcommflag/main.cpp index bbba950..479b8d7 100644
a b using namespace std; 44 44 #include "CommDetectorFactory.h" 45 45 #include "SlotRelayer.h" 46 46 #include "CustomEventRelayer.h" 47 #include "AudioBuffer.h" 47 48 48 49 #define LOC QString("MythCommFlag: ") 49 50 #define LOC_WARN QString("MythCommFlag, Warning: ") … … static QMap<QString,SkipTypes> *init_skip_types(void) 107 108 (*tmp)["blankscene"] = COMM_DETECT_BLANK_SCENE; 108 109 (*tmp)["blank_scene"] = COMM_DETECT_BLANK_SCENE; 109 110 (*tmp)["logo"] = COMM_DETECT_LOGO; 110 (*tmp)["all"] = COMM_DETECT_ALL; 111 (*tmp)["audio"] = (SkipTypes)COMM_DETECT_AUDIO; 112 (*tmp)["all"] = (SkipTypes)(COMM_DETECT_ALL | COMM_DETECT_AUDIO); 111 113 (*tmp)["d2"] = COMM_DETECT_2; 112 114 (*tmp)["d2_logo"] = COMM_DETECT_2_LOGO; 113 115 (*tmp)["d2_blank"] = COMM_DETECT_2_BLANK; 114 116 (*tmp)["d2_scene"] = COMM_DETECT_2_SCENE; 117 (*tmp)["d2_audio"] = (SkipTypes)COMM_DETECT_2_AUDIO; 115 118 (*tmp)["d2_all"] = COMM_DETECT_2_ALL; 116 119 return tmp; 117 120 } -
mythtv/programs/mythcommflag/mythcommflag.pro
diff --git a/mythtv/programs/mythcommflag/mythcommflag.pro b/mythtv/programs/mythcommflag/mythcommflag.pro index b7242cf..d66bbe1 100644
a b target.path = $${PREFIX}/bin 8 8 INSTALLS = target 9 9 10 10 QMAKE_CLEAN += $(TARGET) 11 DEFINES += USEAUDIO 11 12 12 13 # Input 13 14 HEADERS += CommDetectorFactory.h CommDetectorBase.h … … HEADERS += LogoDetectorBase.h SceneChangeDetectorBase.h 31 32 HEADERS += SlotRelayer.h CustomEventRelayer.h 32 33 HEADERS += commandlineparser.h 33 34 35 HEADERS += AudioChangeDetectorBase.h AudioChangeDetector.h 36 HEADERS += AudioBuffer.h 37 34 38 SOURCES += CommDetectorFactory.cpp CommDetectorBase.cpp 35 39 SOURCES += ClassicLogoDetector.cpp 36 40 SOURCES += ClassicSceneChangeDetector.cpp … … SOURCES += HistogramAnalyzer.cpp 47 51 SOURCES += BlankFrameDetector.cpp 48 52 SOURCES += SceneChangeDetector.cpp 49 53 SOURCES += PrePostRollFlagger.cpp 54 SOURCES += AudioChangeDetectorBase.cpp AudioChangeDetector.cpp 55 SOURCES += AudioBuffer.cpp 50 56 51 57 SOURCES += main.cpp commandlineparser.cpp 52 58
