Ticket #10793: comm-detector-audio.1.patch

File comm-detector-audio.1.patch, 54.0 KB (added by Mark Spieth, 7 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
     4AudioSample::AudioSample()
     5{
     6    time = 0;
     7    duration = 0;
     8    power = 0;
     9    channels = 0;
     10    changed = false;
     11}
     12
     13QString 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
     24AudioBuffer::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
     43AudioBuffer::~AudioBuffer()
     44{
     45    //delete [] audiobuffer;
     46    if (output_settings)
     47    {
     48        delete output_settings;
     49        output_settings = NULL;
     50    }
     51}
     52
     53AudioOutputSettings* 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
     67AudioOutputSettings* AudioBuffer::GetOutputSettingsUsers(bool digital)
     68{
     69    if (!output_settings)
     70        output_settings = GetOutputSettings(digital);
     71    return output_settings;
     72}
     73
     74AudioOutputSettings* AudioBuffer::GetOutputSettingsCleaned(bool digital)
     75{
     76    if (!output_settings)
     77        output_settings = GetOutputSettings(digital);
     78    return output_settings;
     79}
     80
     81void AudioBuffer::Enable()
     82{
     83    enabled = true;
     84}
     85
     86// reconfigure sound out for new params
     87void 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
     105void AudioBuffer::SetEffDsp(int /* dsprate */)
     106{
     107    //eff_audiorate = (dsprate / 100);
     108}
     109
     110void AudioBuffer::SetBlocking(bool block)
     111{
     112    (void)block;
     113}
     114
     115void 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
     129bool 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
     141bool 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
     249const 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
     262void AudioBuffer::SetTimecode(int64_t timecode)
     263{
     264    last_audiotime = timecode;
     265}
     266bool AudioBuffer::GetPause(void)
     267{
     268    return false;
     269}
     270void AudioBuffer::Pause(bool paused)
     271{
     272    (void)paused;
     273}
     274void AudioBuffer::Drain(void)
     275{
     276    // Do nothing
     277    return;
     278}
     279bool AudioBuffer::IsPaused() const { return false; }
     280void AudioBuffer::PauseUntilBuffered() { }
     281bool AudioBuffer::IsUpmixing() { return false; }
     282bool AudioBuffer::ToggleUpmix() { return false; }
     283bool AudioBuffer::CanUpmix() { return false; }
     284
     285
     286int64_t AudioBuffer::GetAudiotime(void)
     287{
     288    return last_audiotime;
     289}
     290
     291int AudioBuffer::GetVolumeChannel(int) const
     292{
     293    // Do nothing
     294    return 100;
     295}
     296void AudioBuffer::SetVolumeChannel(int, int)
     297{
     298    // Do nothing
     299}
     300void AudioBuffer::SetVolumeAll(int)
     301{
     302    // Do nothing
     303}
     304int AudioBuffer::GetSWVolume(void)
     305{
     306    return 100;
     307}
     308void AudioBuffer::SetSWVolume(int, bool) {}
     309
     310
     311int AudioBuffer::GetCurrentVolume(void)
     312{
     313    // Do nothing
     314    return 100;
     315}
     316void AudioBuffer::SetCurrentVolume(int)
     317{
     318    // Do nothing
     319}
     320void AudioBuffer::AdjustCurrentVolume(int)
     321{
     322    // Do nothing
     323}
     324void AudioBuffer::SetMute(bool)
     325{
     326    // Do nothing
     327}
     328void AudioBuffer::ToggleMute(void)
     329{
     330    // Do nothing
     331}
     332MuteState AudioBuffer::GetMute(void)
     333{
     334    // Do nothing
     335    return kMuteOff;
     336}
     337MuteState 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
     344void AudioBuffer::bufferOutputData(bool){ return; }
     345int 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
     21class AudioSample : public QSharedData
     22{
     23public:
     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
     33typedef QSharedDataPointer< AudioSample > PAudioSample;
     34
     35
     36#define CHANNELS_MIN 1
     37#define CHANNELS_MAX 8
     38class 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
    - +  
     1using namespace std;
     2
     3#include "AudioChangeDetector.h"
     4
     5AudioChangeDetector::AudioChangeDetector()
     6{
     7}
     8
     9void 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
     12class AudioChangeDetector : public AudioChangeDetectorBase
     13{
     14public:
     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
     4AudioChangeDetectorBase::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
     6class 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; 
    2020
    2121// Commercial Flagging headers
    2222#include "ClassicCommDetector.h"
     23#ifdef USEAUDIO
     24#include "AudioChangeDetector.h"
     25#endif
    2326#include "ClassicLogoDetector.h"
    2427#include "ClassicSceneChangeDetector.h"
     28#include "AudioBuffer.h"
    2529
    2630enum frameAspects {
    2731    COMM_ASPECT_NORMAL = 0,
    static QString toStringFrameMaskValues(int mask, bool verbose) 
    5357            msg += "aspect,";
    5458        if (COMM_FRAME_RATING_SYMBOL & mask)
    5559            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
    5668
    5769        if (msg.length())
    5870            msg = msg.left(msg.length() - 1);
    static QString toStringFrameMaskValues(int mask, bool verbose) 
    6779        msg += (COMM_FRAME_LOGO_PRESENT  & mask) ? "L" : " ";
    6880        msg += (COMM_FRAME_ASPECT_CHANGE & mask) ? "A" : " ";
    6981        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
    7087    }
    7188
    7289    return msg;
    static QString toStringFrameFormats(int format, bool verbose) 
    99116
    100117QString FrameInfoEntry::GetHeader(void)
    101118{
    102     return QString("  frame     min/max/avg scene aspect format flags");
     119    return QString("  frame     min/max/avg scene aspect format  apwr  achan flags");
    103120}
    104121
    105122QString FrameInfoEntry::toString(uint64_t frame, bool verbose) const
    106123{
    107124    return QString(
     125#ifdef USEAUDIO
     126        "%1: %2/%3/%4 %5%  %6 %7 %8 %9 %10")
     127#else
    108128        "%1: %2/%3/%4 %5%  %6 %7 %8")
     129#endif
    109130        .arg(frame,10)
    110131        .arg(minBrightness,3)
    111132        .arg(maxBrightness,3)
    QString FrameInfoEntry::toString(uint64_t frame, bool verbose) const 
    113134        .arg(sceneChangePercent,3)
    114135        .arg(toStringFrameAspects(aspect, verbose))
    115136        .arg(toStringFrameFormats(format, verbose))
     137#ifdef USEAUDIO
     138        .arg(audioPower,8)
     139        .arg(audioMode,6)
     140#endif
    116141        .arg(toStringFrameMaskValues(flagMask, verbose));
    117142}
    118143
    ClassicCommDetector::ClassicCommDetector(SkipType commDetectMethod_in, 
    134159    horizSpacing(0),                           vertSpacing(0),
    135160    fpm(0.0),                                  blankFramesOnly(false),
    136161    blankFrameCount(0),                        currentAspect(0),
     162    silentFrameCount(0),
    137163    totalMinBrightness(0),                     detectBlankFrames(false),
    138164    detectSceneChanges(false),                 detectStationLogo(false),
     165    detectSilentFrames(false),
    139166    logoInfoAvailable(false),                  logoDetector(0),
    140167    framePtr(0),                               frameIsBlank(false),
    141168    sceneHasChanged(false),                    stationLogoPresent(false),
    142169    lastFrameWasBlank(false),                  lastFrameWasSceneChange(false),
    143170    decoderFoundAspectChanges(false),          sceneChangeDetector(0),
     171#if USEAUDIO
     172    audioChangeDetector(0),
     173#endif
    144174    player(player_in),
    145175    startedAt(startedAt_in),                   stopsAt(stopsAt_in),
    146176    recordingStartedAt(recordingStartedAt_in),
    ClassicCommDetector::ClassicCommDetector(SkipType commDetectMethod_in, 
    170200        gCoreContext->GetNumSetting("CommDetectMinShowLength", 65);
    171201    commDetectMaxCommLength =
    172202        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());
    173209
    174210    commDetectBlankCanHaveLogo =
    175211        !!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
    176219}
    177220
    178221void ClassicCommDetector::Init()
    void ClassicCommDetector::Init() 
    257300         this,
    258301         SLOT(sceneChangeDetectorHasNewInformation(unsigned int,bool,float))
    259302    );
     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
    260313
    261314    frameIsBlank = false;
    262315    stationLogoPresent = false;
    void ClassicCommDetector::Init() 
    278331
    279332void ClassicCommDetector::deleteLater(void)
    280333{
     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
    281343    if (sceneChangeDetector)
    282344        sceneChangeDetector->deleteLater();
    283345
    void ClassicCommDetector::deleteLater(void) 
    289351
    290352bool ClassicCommDetector::go()
    291353{
     354#ifdef USEAUDIO
     355    player->GetAudio()->ReinitAudio();
     356#endif
    292357    int secsSince = 0;
    293358    int requiredBuffer = 30;
    294359    int requiredHeadStart = requiredBuffer;
    bool ClassicCommDetector::go() 
    401466
    402467    emit breathe();
    403468
     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));
    404477    player->ResetTotalDuration();
    405478
    406479    while (!player->GetEof())
    void ClassicCommDetector::sceneChangeDetectorHasNewInformation( 
    606679    }
    607680
    608681    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    }
    609687}
    610688
     689#ifdef USEAUDIO
     690void 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
    611701void ClassicCommDetector::GetCommercialBreakList(frm_dir_map_t &marks)
    612702{
    613703
    void ClassicCommDetector::GetCommercialBreakList(frm_dir_map_t &marks) 
    620710    bool blank = COMM_DETECT_BLANK & commDetectMethod;
    621711    bool scene = COMM_DETECT_SCENE & commDetectMethod;
    622712    bool logo  = COMM_DETECT_LOGO  & commDetectMethod;
     713    bool audio = COMM_DETECT_AUDIO & commDetectMethod;
    623714
    624715    if (COMM_DETECT_OFF == commDetectMethod)
    625716        return;
    626717
    627     if (!blank && !scene && !logo)
     718    if (!blank && !scene && !logo && !audio)
    628719    {
    629720        LOG(VB_COMMFLAG, LOG_ERR, QString("Unexpected commDetectMethod: 0x%1")
    630721                .arg(commDetectMethod,0,16));
    void ClassicCommDetector::GetCommercialBreakList(frm_dir_map_t &marks) 
    657748        marks = logoCommBreakMap;
    658749    }
    659750
    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)
    662759    {
    663         if (blank && scene)
     760        marks.clear();
     761        if (blank)
     762        {
     763            marks = Combine2Maps(blankCommBreakMap, marks);
     764        }
     765        if (scene)
    664766        {
    665             marks = commBreakMap = Combine2Maps(
    666                 blankCommBreakMap, sceneCommBreakMap);
     767            marks = Combine2Maps(sceneCommBreakMap, marks);
    667768        }
    668         else if (blank && logo)
     769        if (logo)
    669770        {
    670             marks = commBreakMap = Combine2Maps(
    671                 blankCommBreakMap, logoCommBreakMap);
     771            marks = Combine2Maps(logoCommBreakMap, marks);
    672772        }
    673         else if (scene && logo)
     773        if (audio)
    674774        {
    675             marks = commBreakMap = Combine2Maps(
    676                 sceneCommBreakMap, logoCommBreakMap);
     775            marks = Combine2Maps(audioCommBreakMap, marks);
    677776        }
     777        commBreakMap = marks;
    678778    }
    679779
    680780    LOG(VB_COMMFLAG, LOG_INFO, "Final Commercial Break Map");
    void ClassicCommDetector::ProcessFrame(VideoFrame *frame, 
    807907
    808908    if (commDetectMethod & COMM_DETECT_SCENE)
    809909    {
    810         sceneChangeDetector->processFrame(framePtr);
     910        sceneChangeDetector->processFrame(framePtr, curFrameNumber);
    811911    }
    812912
    813913    stationLogoPresent = false;
    void ClassicCommDetector::ProcessFrame(VideoFrame *frame, 
    9581058    if (stationLogoPresent)
    9591059        flagMask |= COMM_FRAME_LOGO_PRESENT;
    9601060
     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
    9611115    //TODO: move this debugging code out of the perframe loop, and do it after
    9621116    // we've processed all frames. this is because a scenechangedetector can
    9631117    // now use a few frames to determine whether the frame a few frames ago was
    void ClassicCommDetector::ProcessFrame(VideoFrame *frame, 
    9681122
    9691123    if (verboseDebugging)
    9701124        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
    9711128            QString().sprintf("Frame: %6ld -> %3d %3d %3d %3d %1d %1d %04x",
     1129#endif
    9721130                (long)curFrameNumber,
    9731131                frameInfo[curFrameNumber].minBrightness,
    9741132                frameInfo[curFrameNumber].maxBrightness,
    void ClassicCommDetector::ProcessFrame(VideoFrame *frame, 
    9761134                frameInfo[curFrameNumber].sceneChangePercent,
    9771135                frameInfo[curFrameNumber].format,
    9781136                frameInfo[curFrameNumber].aspect,
     1137#ifdef USEAUDIO
     1138                frameInfo[curFrameNumber].audioPower,
     1139                frameInfo[curFrameNumber].audioMode,
     1140#endif
    9791141                frameInfo[curFrameNumber].flagMask ));
    9801142
    9811143#ifdef SHOW_DEBUG_WIN
    void ClassicCommDetector::ClearAllMaps(void) 
    9981160    blankCommBreakMap.clear();
    9991161    sceneMap.clear();
    10001162    sceneCommBreakMap.clear();
     1163    audioCommBreakMap.clear();
    10011164    commBreakMap.clear();
    10021165}
    10031166
    void ClassicCommDetector::GetBlankCommBreakMap(frm_dir_map_t &comms) 
    10211184    comms = blankCommBreakMap;
    10221185}
    10231186
     1187void 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
    10241197void ClassicCommDetector::GetSceneChangeMap(frm_dir_map_t &scenes,
    10251198                                            int64_t start_frame)
    10261199{
    void ClassicCommDetector::UpdateFrameBlock(FrameBlock *fbp, 
    11431316
    11441317    value = finfo.flagMask;
    11451318
     1319    if (value & COMM_FRAME_BLANK)
     1320        fbp->bfCount++;
     1321
    11461322    if (value & COMM_FRAME_LOGO_PRESENT)
    11471323        fbp->logoCount++;
    11481324
    void ClassicCommDetector::UpdateFrameBlock(FrameBlock *fbp, 
    11521328    if (value & COMM_FRAME_SCENE_CHANGE)
    11531329        fbp->scCount++;
    11541330
     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
    11551345    if (finfo.format == format)
    11561346        fbp->formatMatch++;
    11571347
    void ClassicCommDetector::BuildAllMethodsCommList(void) 
    11771367    uint64_t lastStart = 0;
    11781368    uint64_t lastEnd = 0;
    11791369    int64_t firstLogoFrame = -1;
    1180     bool nextFrameIsBlank = false;
    11811370    bool lastFrameWasBlank = false;
     1371    bool lastFrameWasSilent = false;
    11821372    uint64_t formatFrames = 0;
    11831373    int format = COMM_FORMAT_NORMAL;
    11841374    uint64_t aspectFrames = 0;
    void ClassicCommDetector::BuildAllMethodsCommList(void) 
    11881378    frm_dir_map_t tmpCommMap;
    11891379    frm_dir_map_t::iterator it;
    11901380
     1381    //bool preferAudioBreaks = (commDetectMethod & COMM_DETECT_AUDIO);
     1382
    11911383    commBreakMap.clear();
    11921384
    1193     fblock = new FrameBlock[blankFrameCount + 2];
     1385    fblock = new FrameBlock[blankFrameCount + 2 + silentFrameCount + 2];
    11941386
    11951387    curBlock = 0;
    11961388    curFrame = 1;
    void ClassicCommDetector::BuildAllMethodsCommList(void) 
    11981390    fbp = &fblock[curBlock];
    11991391    fbp->start = 0;
    12001392    fbp->bfCount = 0;
     1393    fbp->saCount = 0;
     1394    fbp->aPowerAvg = 0;
     1395    fbp->aPowerMin = 1e40;
     1396    fbp->aPowerMax = 0;
     1397    fbp->acCount = 0;
    12011398    fbp->logoCount = 0;
    12021399    fbp->ratingCount = 0;
    12031400    fbp->scCount = 0;
    void ClassicCommDetector::BuildAllMethodsCommList(void) 
    12071404    fbp->score = 0;
    12081405
    12091406    lastFrameWasBlank = true;
     1407    lastFrameWasSilent = true;
    12101408
    12111409    if (decoderFoundAspectChanges)
    12121410    {
    void ClassicCommDetector::BuildAllMethodsCommList(void) 
    12451443        }
    12461444    }
    12471445
     1446#define SPLIT_MODE 2
    12481447    while (curFrame <= framesProcessed)
    12491448    {
    12501449        value = frameInfo[curFrame].flagMask;
    12511450
    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);
    12571455
    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);
    12861463
    1287             lastFrameWasBlank = true;
    1288         }
    1289         else
     1464        if ((frameInfo[curFrame].sceneChangePercent < 50) && lastFrameWasSilent && !lastFrameWasBlank)
    12901465        {
    1291             lastFrameWasBlank = false;
     1466            newBlockMask |= true;
    12921467        }
     1468#endif
    12931469
     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        }
    12941499        UpdateFrameBlock(fbp, frameInfo[curFrame], format, aspect);
    12951500
    12961501        if ((value & COMM_FRAME_LOGO_PRESENT) &&
    void ClassicCommDetector::BuildAllMethodsCommList(void) 
    13001505        curFrame++;
    13011506    }
    13021507
    1303     fbp->end = curFrame;
     1508    fbp->end = curFrame - 1;
    13041509    fbp->frames = fbp->end - fbp->start + 1;
    13051510    fbp->length = fbp->frames / fps;
    13061511
     1512    fbp->aPowerAvg /= fbp->frames;
     1513
    13071514    if ((fbp->scCount) && (fbp->length > 1.05))
    13081515        fbp->scRate = fbp->scCount / fbp->length;
    13091516
    void ClassicCommDetector::BuildAllMethodsCommList(void) 
    13141521    LOG(VB_COMMFLAG, LOG_INFO, "Initial Block pass");
    13151522    LOG(VB_COMMFLAG, LOG_DEBUG,
    13161523        "Block StTime StFrm  EndFrm Frames Secs    "
    1317         "Bf  Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch Score");
     1524        "Bf  Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch SA Cnt AC Cnt AudPower Score");
    13181525    LOG(VB_COMMFLAG, LOG_INFO,
    13191526        "----- ------ ------ ------ ------ ------- "
    1320         "--- ------ ------ ------ ----- ------ ------ -----");
     1527        "--- ------ ------ ------ ----- ------ ------ ------ -------- -----");
    13211528    while (curBlock <= maxBlock)
    13221529    {
    13231530        fbp = &fblock[curBlock];
    13241531
    13251532        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",
    13271534                    curBlock, (int)(fbp->start / fps) / 60,
    13281535                    (int)((fbp->start / fps )) % 60,
    13291536                    fbp->start, fbp->end, fbp->frames, fbp->length,
    13301537                    fbp->bfCount, fbp->logoCount, fbp->ratingCount,
    13311538                    fbp->scCount, fbp->scRate, fbp->formatMatch,
    1332                     fbp->aspectMatch, fbp->score);
     1539                    fbp->aspectMatch, fbp->saCount, fbp->acCount, fbp->aPowerAvg, fbp->aPowerMin, fbp->aPowerMax, fbp->score);
    13331540        LOG(VB_COMMFLAG, LOG_DEBUG, msg);
    13341541
     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
    13351573        if (fbp->frames > fps)
    13361574        {
    13371575            if (verboseDebugging)
    void ClassicCommDetector::BuildAllMethodsCommList(void) 
    13791617            }
    13801618
    13811619            if ((logoInfoAvailable) &&
    1382                 (fbp->logoCount < (fbp->frames * 0.50)))
     1620                (fbp->logoCount < (fbp->frames * 0.50)) &&
     1621                (fbp->bfCount < (fbp->frames * 0.10)))
    13831622            {
    13841623                if (verboseDebugging)
    13851624                    LOG(VB_COMMFLAG, LOG_DEBUG,
    1386                         "      logoInfoAvailable && logoCount < frames * .50, "
     1625                        "      logoInfoAvailable && logoCount < frames * .50 && blanks < frames * 0.1, "
    13871626                        "-10");
    13881627                fbp->score -= 10;
    13891628            }
    void ClassicCommDetector::BuildAllMethodsCommList(void) 
    13971636            }
    13981637
    13991638            if ((fbp->scRate > 1.0) &&
     1639                (fbp->bfCount < (fbp->frames * 0.50)) &&
    14001640                (fbp->logoCount < (fbp->frames * .90)))
    14011641            {
    14021642                if (verboseDebugging)
    void ClassicCommDetector::BuildAllMethodsCommList(void) 
    14211661                fbp->score -= 20;
    14221662            }
    14231663
    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)
    14271666            {
    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                }
    14321675            }
    14331676        }
    14341677        else
    void ClassicCommDetector::BuildAllMethodsCommList(void) 
    14761719        }
    14771720
    14781721        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",
    14801723                    (int)(fbp->start / fps) / 60,
    14811724                    (int)((fbp->start / fps )) % 60,
    14821725                    fbp->start, fbp->end, fbp->frames, fbp->length,
    14831726                    fbp->bfCount, fbp->logoCount, fbp->ratingCount,
    14841727                    fbp->scCount, fbp->scRate, fbp->formatMatch,
    1485                     fbp->aspectMatch, fbp->score);
     1728                    fbp->aspectMatch, fbp->saCount, fbp->acCount, fbp->aPowerAvg, fbp->aPowerMin, fbp->aPowerMax, fbp->score);
    14861729        LOG(VB_COMMFLAG, LOG_DEBUG, msg);
    14871730
    14881731        lastScore = fbp->score;
    void ClassicCommDetector::BuildAllMethodsCommList(void) 
    14961739    LOG(VB_COMMFLAG, LOG_INFO, "Second Block pass");
    14971740    LOG(VB_COMMFLAG, LOG_DEBUG,
    14981741        "Block StTime StFrm  EndFrm Frames Secs    "
    1499         "Bf  Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch Score");
     1742        "Bf  Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch SA Cnt AC Cnt AudPower Score");
    15001743    LOG(VB_COMMFLAG, LOG_DEBUG,
    15011744        "----- ------ ------ ------ ------ ------- "
    1502         "--- ------ ------ ------ ----- ------ ------ -----");
     1745        "--- ------ ------ ------ ----- ------ ------ ------ ------ -------- -----");
    15031746    while (curBlock <= maxBlock)
    15041747    {
    15051748        fbp = &fblock[curBlock];
    15061749
    15071750        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",
    15091752                    curBlock, (int)(fbp->start / fps) / 60,
    15101753                    (int)((fbp->start / fps )) % 60,
    15111754                    fbp->start, fbp->end, fbp->frames, fbp->length,
    15121755                    fbp->bfCount, fbp->logoCount, fbp->ratingCount,
    15131756                    fbp->scCount, fbp->scRate, fbp->formatMatch,
    1514                     fbp->aspectMatch, fbp->score);
     1757                    fbp->aspectMatch, fbp->saCount, fbp->acCount, fbp->aPowerAvg, fbp->aPowerMin, fbp->aPowerMax, fbp->score);
    15151758        LOG(VB_COMMFLAG, LOG_DEBUG, msg);
    15161759
    15171760        if ((curBlock > 0) && (curBlock < maxBlock))
    void ClassicCommDetector::BuildAllMethodsCommList(void) 
    15371780                        "lastScore < 0 && nextScore < 0, setting -10");
    15381781                fbp->score -= 10;
    15391782            }
     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            }
    15401793
    15411794            if ((fbp->frames < (120*fps)) &&
    15421795                (lastScore < 0) &&
    void ClassicCommDetector::BuildAllMethodsCommList(void) 
    16021855        }
    16031856
    16041857        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",
    16061859                    (int)(fbp->start / fps) / 60,
    16071860                    (int)((fbp->start / fps )) % 60,
    16081861                    fbp->start, fbp->end, fbp->frames, fbp->length,
    16091862                    fbp->bfCount, fbp->logoCount, fbp->ratingCount,
    16101863                    fbp->scCount, fbp->scRate, fbp->formatMatch,
    1611                     fbp->aspectMatch, fbp->score);
     1864                    fbp->aspectMatch, fbp->saCount, fbp->acCount, fbp->aPowerAvg, fbp->aPowerMin, fbp->aPowerMax, fbp->score);
    16121865        LOG(VB_COMMFLAG, LOG_DEBUG, msg);
    16131866
    16141867        lastScore = fbp->score;
    void ClassicCommDetector::BuildAllMethodsCommList(void) 
    16191872    LOG(VB_COMMFLAG, LOG_INFO, "FINAL Block stats");
    16201873    LOG(VB_COMMFLAG, LOG_DEBUG,
    16211874        "Block StTime StFrm  EndFrm Frames Secs    "
    1622         "Bf  Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch Score");
     1875        "Bf  Lg Cnt RT Cnt SC Cnt SC Rt FmtMch AspMch SA Cnt AC Cnt AudPower Score");
    16231876    LOG(VB_COMMFLAG, LOG_DEBUG,
    16241877        "----- ------ ------ ------ ------ ------- "
    1625         "--- ------ ------ ------ ----- ------ ------ -----");
     1878        "--- ------ ------ ------ ----- ------ ------ ------ ------ -------- -----");
    16261879    curBlock = 0;
    16271880    lastScore = 0;
    16281881    breakStart = -1;
    void ClassicCommDetector::BuildAllMethodsCommList(void) 
    17802033        }
    17812034
    17822035        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",
    17842037                    curBlock, (int)(fbp->start / fps) / 60,
    17852038                    (int)((fbp->start / fps )) % 60,
    17862039                    fbp->start, fbp->end, fbp->frames, fbp->length,
    17872040                    fbp->bfCount, fbp->logoCount, fbp->ratingCount,
    17882041                    fbp->scCount, fbp->scRate, fbp->formatMatch,
    1789                     fbp->aspectMatch, thisScore);
     2042                    fbp->aspectMatch, fbp->saCount, fbp->acCount, fbp->aPowerAvg, fbp->aPowerMin, fbp->aPowerMax, thisScore);
    17902043        LOG(VB_COMMFLAG, LOG_DEBUG, msg);
    17912044
    17922045        lastScore = thisScore;
    void ClassicCommDetector::BuildBlankFrameCommList(void) 
    20332286                .arg(it.key()).arg(*it));
    20342287}
    20352288
     2289void ClassicCommDetector::BuildAudioFrameCommList(void)
     2290{
     2291    LOG(VB_COMMFLAG, LOG_INFO, "CommDetect::BuildBlankFrameCommList()");
     2292
     2293    audioCommBreakMap.clear();
     2294    // TODO
     2295}
    20362296
    20372297void ClassicCommDetector::BuildSceneChangeCommList(void)
    20382298{
  • 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; 
    2020class LogoDetectorBase;
    2121class SceneChangeDetectorBase;
    2222
     23#ifdef USEAUDIO
     24class AudioChangeDetectorBase;
     25class AudioBuffer;
     26#endif
     27
    2328enum frameMaskValues {
    2429    COMM_FRAME_SKIPPED       = 0x0001,
    2530    COMM_FRAME_BLANK         = 0x0002,
    enum frameMaskValues { 
    2732    COMM_FRAME_LOGO_PRESENT  = 0x0008,
    2833    COMM_FRAME_ASPECT_CHANGE = 0x0010,
    2934    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
    3040};
    3141
    3242class FrameInfoEntry
    class FrameInfoEntry 
    3848    int sceneChangePercent;
    3949    int aspect;
    4050    int format;
     51#ifdef USEAUDIO
     52    double audioPower;
     53    int audioMode;
     54#endif
    4155    int flagMask;
    4256    static QString GetHeader(void);
    4357    QString toString(uint64_t frame, bool verbose) const;
    class ClassicCommDetector : public CommDetectorBase 
    8094            long frames;
    8195            double length;
    8296            int bfCount;
     97            int saCount;
     98            int acCount;
     99            double aPowerAvg;
     100            double aPowerMin;
     101            double aPowerMax;
    83102            int logoCount;
    84103            int ratingCount;
    85104            int scCount;
    class ClassicCommDetector : public CommDetectorBase 
    93112        void ClearAllMaps(void);
    94113        void GetBlankCommMap(frm_dir_map_t &comms);
    95114        void GetBlankCommBreakMap(frm_dir_map_t &comms);
     115        void GetSilentCommMap(frm_dir_map_t &comms);
     116        void GetAudioCommBreakMap(frm_dir_map_t &comms);
    96117        void GetSceneChangeMap(frm_dir_map_t &scenes,
    97118                               int64_t start_frame);
    98119        frm_dir_map_t Combine2Maps(
    class ClassicCommDetector : public CommDetectorBase 
    101122                              int format, int aspect);
    102123        void BuildAllMethodsCommList(void);
    103124        void BuildBlankFrameCommList(void);
     125        void BuildAudioFrameCommList(void);
    104126        void BuildSceneChangeCommList(void);
    105127        void BuildLogoCommList();
    106128        void MergeBlankCommList(void);
    class ClassicCommDetector : public CommDetectorBase 
    128150        int commDetectMinShowLength;
    129151        int commDetectMaxCommLength;
    130152        bool commDetectBlankCanHaveLogo;
     153        int commDetectLargeSceneChangeThreshold;
     154        QList<float> commDetectCommLengths;
    131155
    132156        bool verboseDebugging;
    133157
    class ClassicCommDetector : public CommDetectorBase 
    142166        bool blankFramesOnly;
    143167        int blankFrameCount;
    144168        int currentAspect;
     169        int silentFrameCount;
    145170
    146171
    147172        int totalMinBrightness;
    class ClassicCommDetector : public CommDetectorBase 
    149174        bool detectBlankFrames;
    150175        bool detectSceneChanges;
    151176        bool detectStationLogo;
     177        bool detectSilentFrames;
    152178
    153179        bool logoInfoAvailable;
    154180        LogoDetectorBase* logoDetector;
    class ClassicCommDetector : public CommDetectorBase 
    158184        frm_dir_map_t blankFrameMap;
    159185        frm_dir_map_t blankCommMap;
    160186        frm_dir_map_t blankCommBreakMap;
     187        frm_dir_map_t silentFrameMap;
     188        frm_dir_map_t audioCommBreakMap;
    161189        frm_dir_map_t sceneMap;
    162190        frm_dir_map_t sceneCommBreakMap;
    163191        frm_dir_map_t commBreakMap;
    class ClassicCommDetector : public CommDetectorBase 
    172200        bool decoderFoundAspectChanges;
    173201
    174202        SceneChangeDetectorBase* sceneChangeDetector;
     203#if USEAUDIO
     204        AudioChangeDetectorBase* audioChangeDetector;
     205#endif
    175206
    176207protected:
    177208        MythPlayer *player;
    protected: 
    191222        void SetVideoParams(float aspect);
    192223        void ProcessFrame(VideoFrame *frame, long long frame_number);
    193224        QMap<long long, FrameInfoEntry> frameInfo;
     225#ifdef USEAUDIO
     226        AudioBuffer *audioBuffer;
     227        int64_t audioFrame;
     228#endif
    194229
    195230public slots:
    196231        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
    197235};
    198236
    199237#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  
    11#include <algorithm>
    22using namespace std;
    33
     4// MythTV headers
     5#include "mythcontext.h"
     6
    47#include "ClassicSceneChangeDetector.h"
    58#include "Histogram.h"
    69
    ClassicSceneChangeDetector::ClassicSceneChangeDetector(unsigned int width, 
    1619{
    1720    histogram = new Histogram;
    1821    previousHistogram = new Histogram;
     22    commDetectSceneChangeThreshold =
     23        gCoreContext->GetNumSetting("CommDetectSceneChangeThreshold", 60)/100.0;
    1924}
    2025
    2126void ClassicSceneChangeDetector::deleteLater(void)
    void ClassicSceneChangeDetector::deleteLater(void) 
    2530    SceneChangeDetectorBase::deleteLater();
    2631}
    2732
    28 void ClassicSceneChangeDetector::processFrame(unsigned char* frame)
     33void ClassicSceneChangeDetector::processFrame(unsigned char* frame, long long frameNumber)
    2934{
    3035    histogram->generateFromImage(frame, width, height, commdetectborder,
    3136                                 width-commdetectborder, commdetectborder,
    3237                                 height-commdetectborder, xspacing, yspacing);
    3338    float similar = histogram->calculateSimilarityWith(*previousHistogram);
    3439
    35     bool isSceneChange = (similar < .85 && !previousFrameWasSceneChange);
     40    bool isSceneChange = (similar < commDetectSceneChangeThreshold && !previousFrameWasSceneChange);
    3641
    3742    emit(haveNewInformation(frameNumber,isSceneChange,similar));
    3843    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 
    1313        unsigned int yspacing);
    1414    virtual void deleteLater(void);
    1515
    16     void processFrame(unsigned char* frame);
     16    void processFrame(unsigned char* frame, long long frameNumber);
    1717
    1818  private:
    1919    ~ClassicSceneChangeDetector() {}
    class ClassicSceneChangeDetector : public SceneChangeDetectorBase 
    2525    bool previousFrameWasSceneChange;
    2626    unsigned int xspacing, yspacing;
    2727    unsigned int commdetectborder;
     28    double commDetectSceneChangeThreshold;
    2829};
    2930
    3031#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 
    1111    SceneChangeDetectorBase(unsigned int w, unsigned int h) :
    1212        width(w), height(h) {}
    1313
    14     virtual void processFrame(unsigned char *frame) = 0;
     14    virtual void processFrame(unsigned char *frame, long long frameNumber) = 0;
    1515
    1616  signals:
    1717    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; 
    4444#include "CommDetectorFactory.h"
    4545#include "SlotRelayer.h"
    4646#include "CustomEventRelayer.h"
     47#include "AudioBuffer.h"
    4748
    4849#define LOC      QString("MythCommFlag: ")
    4950#define LOC_WARN QString("MythCommFlag, Warning: ")
    static QMap<QString,SkipTypes> *init_skip_types(void) 
    107108    (*tmp)["blankscene"]  = COMM_DETECT_BLANK_SCENE;
    108109    (*tmp)["blank_scene"] = COMM_DETECT_BLANK_SCENE;
    109110    (*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);
    111113    (*tmp)["d2"]          = COMM_DETECT_2;
    112114    (*tmp)["d2_logo"]     = COMM_DETECT_2_LOGO;
    113115    (*tmp)["d2_blank"]    = COMM_DETECT_2_BLANK;
    114116    (*tmp)["d2_scene"]    = COMM_DETECT_2_SCENE;
     117    (*tmp)["d2_audio"]    = (SkipTypes)COMM_DETECT_2_AUDIO;
    115118    (*tmp)["d2_all"]      = COMM_DETECT_2_ALL;
    116119    return tmp;
    117120}
  • 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 
    88INSTALLS = target
    99
    1010QMAKE_CLEAN += $(TARGET)
     11DEFINES += USEAUDIO
    1112
    1213# Input
    1314HEADERS += CommDetectorFactory.h CommDetectorBase.h
    HEADERS += LogoDetectorBase.h SceneChangeDetectorBase.h 
    3132HEADERS += SlotRelayer.h CustomEventRelayer.h
    3233HEADERS += commandlineparser.h
    3334
     35HEADERS += AudioChangeDetectorBase.h AudioChangeDetector.h
     36HEADERS += AudioBuffer.h
     37
    3438SOURCES += CommDetectorFactory.cpp CommDetectorBase.cpp
    3539SOURCES += ClassicLogoDetector.cpp
    3640SOURCES += ClassicSceneChangeDetector.cpp
    SOURCES += HistogramAnalyzer.cpp 
    4751SOURCES += BlankFrameDetector.cpp
    4852SOURCES += SceneChangeDetector.cpp
    4953SOURCES += PrePostRollFlagger.cpp
     54SOURCES += AudioChangeDetectorBase.cpp AudioChangeDetector.cpp
     55SOURCES += AudioBuffer.cpp
    5056
    5157SOURCES += main.cpp commandlineparser.cpp
    5258