Ticket #1104: mythtv_ac3.17.patch

File mythtv_ac3.17.patch, 91.5 KB (added by Mark Spieth, 18 years ago)
  • libs/libmyth/libmyth.pro

     
    3434SOURCES += virtualkeyboard.cpp mythobservable.cpp
    3535
    3636INCLUDEPATH += ../libmythsamplerate ../libmythsoundtouch ../..
     37INCLUDEPATH += ../libavutil ..
    3738DEPENDPATH += ../libmythsamplerate ../libmythsoundtouch
     39DEPENDPATH += ../libavutil ../libavcodec
    3840
    3941
    4042LIBS += -L../libmythsamplerate -lmythsamplerate-$${LIBVERSION}
    4143LIBS += -L../libmythsoundtouch -lmythsoundtouch-$${LIBVERSION}
     44LIBS += -L../libavcodec -lmythavcodec-$${LIBVERSION}
    4245
    4346isEmpty(QMAKE_EXTENSION_SHLIB) {
    4447  QMAKE_EXTENSION_SHLIB=so
  • libs/libmyth/audiooutput.h

     
    3030    virtual ~AudioOutput() { };
    3131
    3232    // reconfigure sound out for new params
    33     virtual void Reconfigure(int audio_bits, int audio_channels,
    34                              int audio_samplerate, bool audio_passthru) = 0;
     33    virtual void Reconfigure(int audio_bits,
     34                             int audio_channels,
     35                             int audio_samplerate,
     36                             bool audio_passthru,
     37                             void* audio_codec = NULL
     38                             ) = 0;
    3539   
    3640    virtual void SetStretchFactor(float factor);
    3741
     
    7377        lastError = msg;
    7478        VERBOSE(VB_IMPORTANT, "AudioOutput Error: " + lastError);
    7579    }
     80    void ClearError()
     81     { lastError = QString::null; };
    7682
    7783    void Warn(QString msg)
    7884    {
  • libs/libmyth/audiooutputdx.h

     
    2222
    2323    virtual void Reset(void);
    2424    virtual void Reconfigure(int audio_bits,
    25                          int audio_channels, int audio_samplerate);
     25                         int audio_channels,
     26                         int audio_samplerate,
     27                         bool audio_passthru,
     28                         AudioCodecMode aom = AUDIOCODECMODE_NORMAL);
    2629    virtual void SetBlocking(bool blocking);
    2730
    2831    virtual bool AddSamples(char *buffer, int samples, long long timecode);
  • libs/libmyth/audiooutputdx.cpp

     
    119119    // FIXME: kedl: not sure what else could be required here?
    120120}
    121121
    122 void AudioOutputDX::Reconfigure(int audio_bits, int audio_channels,
    123                                 int audio_samplerate, int audio_passthru)
     122void AudioOutputDX::Reconfigure(int audio_bits,
     123                                int audio_channels,
     124                                int audio_samplerate,
     125                                int audio_passthru,
     126                                AudioCodecMode laom
     127                                )
    124128{
    125129    if (dsbuffer)
    126130        DestroyDSBuffer();
  • libs/libmyth/audiooutputbase.h

     
    1212#include "samplerate.h"
    1313#include "SoundTouch.h"
    1414
    15 #define AUDBUFSIZE 768000
     15struct AVCodecContext;
     16class DigitalEncoder;
    1617
     18//#define AUDBUFSIZE 768000
     19//divisible by 12,10,8,6,4,2 and around 1024000
     20//#define AUDBUFSIZE 1024080
     21#define AUDBUFSIZE 1536000
     22
    1723class AudioOutputBase : public AudioOutput
    1824{
    1925 public:
     
    2430    virtual ~AudioOutputBase();
    2531
    2632    // reconfigure sound out for new params
    27     virtual void Reconfigure(int audio_bits, int audio_channels,
    28                              int audio_samplerate, bool audio_passthru);
     33    virtual void Reconfigure(int audio_bits,
     34                             int audio_channels,
     35                             int audio_samplerate,
     36                             bool audio_passthru,
     37                             void* audio_codec = NULL);
    2938   
    3039    // do AddSamples calls block?
    3140    virtual void SetBlocking(bool blocking);
     
    109118
    110119    float audio_stretchfactor;
    111120    AudioOutputSource source;
     121    AVCodecContext *audio_codec;
    112122
    113123    bool killaudio;
    114124
     
    116126    bool set_initial_vol;
    117127    bool buffer_output_data_for_use; //  used by AudioOutputNULL
    118128   
     129    int configured_audio_channels;
     130
    119131 private:
    120132    // resampler
    121133    bool need_resampler;
     
    126138
    127139    // timestretch
    128140    soundtouch::SoundTouch * pSoundStretch;
     141    DigitalEncoder * encoder;
    129142
    130143    bool blocking; // do AddSamples calls block?
    131144
     
    141154
    142155    pthread_mutex_t avsync_lock; /* must hold avsync_lock to read or write
    143156                                    'audiotime' and 'audiotime_updated' */
    144     int audiotime; // timecode of audio leaving the soundcard (same units as
     157    long long audiotime; // timecode of audio leaving the soundcard (same units as
    145158                   //                                          timecodes) ...
    146159    struct timeval audiotime_updated; // ... which was last updated at this time
    147160
    148161    /* Audio circular buffer */
    149162    unsigned char audiobuffer[AUDBUFSIZE];  /* buffer */
    150163    int raud, waud;     /* read and write positions */
    151     int audbuf_timecode;    /* timecode of audio most recently placed into
     164    long long audbuf_timecode;    /* timecode of audio most recently placed into
    152165                   buffer */
    153166
    154167    int numlowbuffer;
  • libs/libmyth/audiooutputbase.cpp

     
    1212#include <sys/time.h>
    1313#include <unistd.h>
    1414
     15extern "C" {
     16#include "libavcodec/avcodec.h"
     17#include "libavcodec/liba52/a52.h"
     18}
    1519
     20#if QT_VERSION < 0x030200
     21#define LONGLONGCONVERT (long)
     22#else
     23#define LONGLONGCONVERT
     24#endif
     25
     26#define LOC QString("DEnc: ");
     27#define MAX_AC3_FRAME_SIZE 6144
     28class DigitalEncoder
     29{
     30public:
     31    DigitalEncoder();
     32    ~DigitalEncoder();
     33    void Dispose();
     34    bool DigitalEncoder::Init(CodecID codec_id, int bitrate, int samplerate, int channels);
     35    size_t Encode(short * buff);
     36
     37    // if needed
     38    char * GetFrameBuffer()
     39    {
     40        if (!frame_buffer && av_context)
     41        {
     42            frame_buffer = new char [one_frame_bytes];
     43        }
     44        return frame_buffer;
     45    }   
     46    size_t FrameSize() const { return one_frame_bytes; }
     47    char * GetOutBuff() const { return outbuf; }
     48
     49    size_t audio_bytes_per_sample;
     50private:
     51    AVCodecContext *av_context;
     52    char * outbuf;
     53    char * frame_buffer;
     54    int outbuf_size;
     55    size_t one_frame_bytes;
     56};
     57
     58DigitalEncoder::DigitalEncoder()
     59{
     60    av_context = NULL;
     61    outbuf = NULL;
     62    outbuf_size = 0;
     63    one_frame_bytes = 0;
     64    frame_buffer = NULL;
     65}
     66
     67DigitalEncoder::~DigitalEncoder()
     68{
     69    Dispose();
     70}
     71
     72void DigitalEncoder::Dispose()
     73{
     74    if (av_context)
     75    {
     76        avcodec_close(av_context);
     77        av_free(av_context);
     78        av_context = NULL;
     79    }
     80    if (outbuf)
     81    {
     82        delete [] outbuf;
     83        outbuf = NULL;
     84        outbuf_size = 0;
     85    }
     86    if (frame_buffer)
     87    {
     88        delete [] frame_buffer;
     89        frame_buffer = NULL;
     90        one_frame_bytes = 0;
     91    }
     92}
     93
     94//CODEC_ID_AC3
     95bool DigitalEncoder::Init(CodecID codec_id, int bitrate, int samplerate, int channels)
     96{
     97    AVCodec * codec;
     98    int ret;
     99
     100    VERBOSE(VB_AUDIO, QString("DigitalEncoder::Init codecid=%1, br=%2, sr=%3, ch=%4")
     101            .arg(codec_id_string(codec_id))
     102            .arg(bitrate)
     103            .arg(samplerate)
     104            .arg(channels));
     105    //codec = avcodec_find_encoder(codec_id);
     106    // always AC3 as there is no DTS encoder at the moment 2005/1/9
     107    codec = avcodec_find_encoder(CODEC_ID_AC3);
     108    if (!codec)
     109    {
     110        VERBOSE(VB_IMPORTANT,"Error: could not find codec");
     111        return false;
     112    }
     113    av_context = avcodec_alloc_context();
     114    av_context->bit_rate = bitrate;
     115    av_context->sample_rate = samplerate;
     116    av_context->channels = channels;
     117    // open it */
     118    if ((ret = avcodec_open(av_context, codec)) < 0)
     119    {
     120        VERBOSE(VB_IMPORTANT,"Error: could not open codec, invalid bitrate or samplerate");
     121        Dispose();
     122        return false;
     123    }
     124
     125    size_t bytes_per_frame = av_context->channels * sizeof(short);
     126    audio_bytes_per_sample = bytes_per_frame;
     127    one_frame_bytes = bytes_per_frame * av_context->frame_size;
     128
     129    outbuf_size = 16384;    // ok for AC3 but DTS?
     130    outbuf = new char [outbuf_size];
     131    VERBOSE(VB_AUDIO, QString("DigitalEncoder::Init fs=%1, bpf=%2 ofb=%3")
     132            .arg(av_context->frame_size)
     133            .arg(bytes_per_frame)
     134            .arg(one_frame_bytes)
     135           );
     136
     137    return true;
     138}
     139
     140static int DTS_SAMPLEFREQS[16] =
     141{
     142    0,      8000,   16000,  32000,  64000,  128000, 11025,  22050,
     143    44100,  88200,  176400, 12000,  24000,  48000,  96000,  192000
     144};
     145
     146static int DTS_BITRATES[30] =
     147{
     148    32000,    56000,    64000,    96000,    112000,   128000,
     149    192000,   224000,   256000,   320000,   384000,   448000,
     150    512000,   576000,   640000,   768000,   896000,   1024000,
     151    1152000,  1280000,  1344000,  1408000,  1411200,  1472000,
     152    1536000,  1920000,  2048000,  3072000,  3840000,  4096000
     153};
     154
     155static int dts_decode_header(uint8_t *indata_ptr, int *rate,
     156                             int *nblks, int *sfreq)
     157{
     158    uint id = ((indata_ptr[0] << 24) | (indata_ptr[1] << 16) |
     159               (indata_ptr[2] << 8)  | (indata_ptr[3]));
     160
     161    if (id != 0x7ffe8001)
     162        return -1;
     163
     164    int ftype = indata_ptr[4] >> 7;
     165
     166    int surp = (indata_ptr[4] >> 2) & 0x1f;
     167    surp = (surp + 1) % 32;
     168
     169    *nblks = (indata_ptr[4] & 0x01) << 6 | (indata_ptr[5] >> 2);
     170    ++*nblks;
     171
     172    int fsize = (indata_ptr[5] & 0x03) << 12 |
     173                (indata_ptr[6]         << 4) | (indata_ptr[7] >> 4);
     174    ++fsize;
     175
     176    *sfreq = (indata_ptr[8] >> 2) & 0x0f;
     177    *rate = (indata_ptr[8] & 0x03) << 3 | ((indata_ptr[9] >> 5) & 0x07);
     178
     179    if (ftype != 1)
     180    {
     181        VERBOSE(VB_IMPORTANT, LOC +
     182                QString("DTS: Termination frames not handled (ftype %1)")
     183                .arg(ftype));
     184        return -1;
     185    }
     186
     187    if (*sfreq != 13)
     188    {
     189        VERBOSE(VB_IMPORTANT, LOC +
     190                QString("DTS: Only 48kHz supported (sfreq %1)").arg(*sfreq));
     191        return -1;
     192    }
     193
     194    if ((fsize > 8192) || (fsize < 96))
     195    {
     196        VERBOSE(VB_IMPORTANT, LOC +
     197                QString("DTS: fsize: %1 invalid").arg(fsize));
     198        return -1;
     199    }
     200
     201    if (*nblks != 8 && *nblks != 16 && *nblks != 32 &&
     202        *nblks != 64 && *nblks != 128 && ftype == 1)
     203    {
     204        VERBOSE(VB_IMPORTANT, LOC +
     205                QString("DTS: nblks %1 not valid for normal frame")
     206                .arg(*nblks));
     207        return -1;
     208    }
     209
     210    return fsize;
     211}
     212
     213static int dts_syncinfo(uint8_t *indata_ptr, int * /*flags*/,
     214                        int *sample_rate, int *bit_rate)
     215{
     216    int nblks;
     217    int rate;
     218    int sfreq;
     219
     220    int fsize = dts_decode_header(indata_ptr, &rate, &nblks, &sfreq);
     221    if (fsize >= 0)
     222    {
     223        if (rate >= 0 && rate <= 29)
     224            *bit_rate = DTS_BITRATES[rate];
     225        else
     226            *bit_rate = 0;
     227        if (sfreq >= 1 && sfreq <= 15)
     228            *sample_rate = DTS_SAMPLEFREQS[sfreq];
     229        else
     230            *sample_rate = 0;
     231    }
     232    return fsize;
     233}
     234
     235static int encode_frame(
     236        bool dts,
     237        unsigned char *data,
     238        size_t &len)
     239{
     240    size_t enc_len;
     241    int flags, sample_rate, bit_rate;
     242
     243    // we don't do any length/crc validation of the AC3 frame here; presumably
     244    // the receiver will have enough sense to do that.  if someone has a
     245    // receiver that doesn't, here would be a good place to put in a call
     246    // to a52_crc16_block(samples+2, data_size-2) - but what do we do if the
     247    // packet is bad?  we'd need to send something that the receiver would
     248    // ignore, and if so, may as well just assume that it will ignore
     249    // anything with a bad CRC...
     250
     251    uint nr_samples = 0, block_len;
     252    if (dts)
     253    {
     254        enc_len = dts_syncinfo(data+8, &flags, &sample_rate, &bit_rate);
     255        int rate, sfreq, nblks;
     256        dts_decode_header(data+8, &rate, &nblks, &sfreq);
     257        nr_samples = nblks * 32;
     258        block_len = nr_samples * 2 * 2;
     259    }
     260    else
     261    {
     262        enc_len = a52_syncinfo(data+8, &flags, &sample_rate, &bit_rate);
     263        block_len = MAX_AC3_FRAME_SIZE;
     264    }
     265
     266    if (enc_len == 0 || enc_len > len)
     267    {
     268        int l = len;
     269        len = 0;
     270        return l;
     271    }
     272
     273    enc_len = min((uint)enc_len, block_len - 8);
     274
     275    //uint32_t x = *(uint32_t*)(data+8);
     276    // in place swab
     277    swab(data+8, data+8, enc_len);
     278    //VERBOSE(VB_AUDIO|VB_TIMESTAMP,
     279    //        QString("DigitalEncoder::Encode swab test %1 %2")
     280    //        .arg(x,0,16).arg(*(uint32_t*)(data+8),0,16));
     281
     282    // the following values come from libmpcodecs/ad_hwac3.c in mplayer.
     283    // they form a valid IEC958 AC3 header.
     284    data[0] = 0x72;
     285    data[1] = 0xF8;
     286    data[2] = 0x1F;
     287    data[3] = 0x4E;
     288    data[4] = 0x01;
     289    if (dts)
     290    {
     291        switch(nr_samples)
     292        {
     293            case 512:
     294                data[4] = 0x0B;      /* DTS-1 (512-sample bursts) */
     295                break;
     296
     297            case 1024:
     298                data[4] = 0x0C;      /* DTS-2 (1024-sample bursts) */
     299                break;
     300
     301            case 2048:
     302                data[4] = 0x0D;      /* DTS-3 (2048-sample bursts) */
     303                break;
     304
     305            default:
     306                VERBOSE(VB_IMPORTANT, LOC +
     307                        QString("DTS: %1-sample bursts not supported")
     308                        .arg(nr_samples));
     309                data[4] = 0x00;
     310                break;
     311        }
     312    }
     313    data[5] = 0x00;
     314    data[6] = (enc_len << 3) & 0xFF;
     315    data[7] = (enc_len >> 5) & 0xFF;
     316    memset(data + 8 + enc_len, 0, block_len - 8 - enc_len);
     317    len = block_len;
     318
     319    return enc_len;
     320}
     321
     322// must have exactly 1 frames worth of data
     323size_t DigitalEncoder::Encode(short * buff)
     324{
     325    int encsize = 0;
     326    size_t outsize = 0;
     327 
     328    // put data in the correct spot for encode frame
     329    outsize = avcodec_encode_audio(
     330                av_context,
     331                ((uchar*)outbuf)+8,
     332                outbuf_size-8,
     333                buff);
     334    size_t tmpsize = outsize;
     335
     336    outsize = MAX_AC3_FRAME_SIZE;
     337    encsize = encode_frame(
     338            //av_context->codec_id==CODEC_ID_DTS,
     339            false,
     340            (unsigned char*)outbuf, outsize);
     341    VERBOSE(VB_AUDIO|VB_TIMESTAMP,
     342            QString("DigitalEncoder::Encode len1=%1 len2=%2 finallen=%3")
     343                .arg(tmpsize)
     344                .arg(encsize)
     345                .arg(outsize)
     346           );
     347
     348    return outsize;
     349}
     350#undef LOC
     351#define LOC QString("AO: ")
     352
    16353AudioOutputBase::AudioOutputBase(QString audiodevice, int,
    17354                                 int, int,
    18355                                 AudioOutputSource source,
     
    31368    current_seconds = -1;
    32369    source_bitrate = -1;
    33370    audio_stretchfactor = 1.0;
     371    audio_codec = NULL;
    34372    pSoundStretch = NULL;
     373    encoder = NULL;
    35374    blocking = false;
    36375    this->source = source;
    37376    this->set_initial_vol = set_initial_vol;
    38377    soundcard_buffer_size = 0;
    39378    buffer_output_data_for_use = false; // used by AudioOutputNULL
     379    configured_audio_channels = gContext->GetNumSetting("MaxChannels", 2);
    40380
    41 
    42381    src_ctx = NULL;
    43382
    44383    // You need to call the next line from your concrete class.
     
    80419            VERBOSE(VB_GENERAL, QString("Using time stretch %1")
    81420                                        .arg(audio_stretchfactor));
    82421            pSoundStretch = new soundtouch::SoundTouch();
    83             pSoundStretch->setSampleRate(audio_samplerate);
    84             pSoundStretch->setChannels(audio_channels);
     422            if (audio_codec)
     423            {
     424                if (!encoder)
     425                {
     426                    VERBOSE(VB_AUDIO, LOC + QString("Creating Encoder for codec %1 origfs %2").arg(audio_codec->codec_id).arg(audio_codec->frame_size));
     427                    encoder = new DigitalEncoder();
     428                    if (!encoder->Init(audio_codec->codec_id,
     429                                audio_codec->bit_rate,
     430                                audio_codec->sample_rate,
     431                                audio_codec->channels
     432                                ))
     433                    {
     434                        // eeks
     435                        delete encoder;
     436                        encoder = NULL;
     437                        VERBOSE(VB_AUDIO, LOC + QString("Failed to Create Encoder"));
     438                    }
     439                }
     440            }
     441            if (encoder)
     442            {
     443                pSoundStretch->setSampleRate(audio_codec->sample_rate);
     444                pSoundStretch->setChannels(audio_codec->channels);
     445            }
     446            else
     447            {
     448                pSoundStretch->setSampleRate(audio_samplerate);
     449                pSoundStretch->setChannels(audio_channels);
     450            }
    85451
    86452            pSoundStretch->setTempo(audio_stretchfactor);
    87453            pSoundStretch->setSetting(SETTING_SEQUENCE_MS, 35);
     
    104470}
    105471
    106472void AudioOutputBase::Reconfigure(int laudio_bits, int laudio_channels,
    107                                  int laudio_samplerate, bool laudio_passthru)
     473                                 int laudio_samplerate, bool laudio_passthru,
     474                                 void* laudio_codec)
    108475{
     476    int codec_id = CODEC_ID_NONE;
     477    int lcodec_id = CODEC_ID_NONE;
     478    int lcchannels = 0;
     479    int cchannels = 0;
     480    if (laudio_codec)
     481    {
     482        lcodec_id = ((AVCodecContext*)laudio_codec)->codec_id;
     483        laudio_bits = 16;
     484        laudio_channels = 2;
     485        laudio_samplerate = 48000;
     486        lcchannels = ((AVCodecContext*)laudio_codec)->channels;
     487    }
     488    if (audio_codec)
     489    {
     490        codec_id = audio_codec->codec_id;
     491        cchannels = ((AVCodecContext*)audio_codec)->channels;
     492    }
     493    ClearError();
    109494    if (laudio_bits == audio_bits && laudio_channels == audio_channels &&
    110         laudio_samplerate == audio_samplerate &&
    111         laudio_passthru == audio_passthru && !need_resampler)
     495        laudio_samplerate == audio_samplerate && !need_resampler &&
     496        laudio_passthru == audio_passthru &&
     497        lcodec_id == codec_id && lcchannels == cchannels)
    112498        return;
    113499
    114500    KillAudio();
     
    120506    waud = raud = 0;
    121507    audio_actually_paused = false;
    122508   
     509    bool redo_stretch = (pSoundStretch && audio_channels != laudio_channels);
    123510    audio_channels = laudio_channels;
    124511    audio_bits = laudio_bits;
    125512    audio_samplerate = laudio_samplerate;
     513    audio_codec = (AVCodecContext*)laudio_codec;
    126514    audio_passthru = laudio_passthru;
    127515    if (audio_bits != 8 && audio_bits != 16)
    128516    {
     
    141529   
    142530    numlowbuffer = 0;
    143531
    144     VERBOSE(VB_GENERAL, QString("Opening audio device '%1'.")
    145             .arg(audiodevice));
     532    VERBOSE(VB_GENERAL, QString("Opening audio device '%1'. ch %2 sr %3")
     533            .arg(audiodevice).arg(audio_channels).arg(audio_samplerate));
    146534   
    147535    // Actually do the device specific open call
    148536    if (!OpenDevice())
    149537    {
    150         VERBOSE(VB_AUDIO, "Aborting reconfigure");
    151538        pthread_mutex_unlock(&avsync_lock);
    152539        pthread_mutex_unlock(&audio_buflock);
     540        if (GetError().isEmpty())
     541            Error("Aborting reconfigure");
     542        VERBOSE(VB_AUDIO, "Aborting reconfigure");
    153543        return;
    154544    }
    155545
     
    171561    current_seconds = -1;
    172562    source_bitrate = -1;
    173563
     564    // NOTE: this wont do anything as above samplerate vars are set equal
    174565    // Check if we need the resampler
    175566    if (audio_samplerate != laudio_samplerate)
    176567    {
     
    194585    }
    195586
    196587    VERBOSE(VB_AUDIO, QString("Audio Stretch Factor: %1").arg(audio_stretchfactor));
     588    VERBOSE(VB_AUDIO, QString("Audio Codec Used: %1")
     589            .arg(audio_codec?codec_id_string(audio_codec->codec_id):"not set"));
    197590
    198     SetStretchFactorLocked(audio_stretchfactor);
    199     if (pSoundStretch)
     591    if (redo_stretch)
    200592    {
    201         pSoundStretch->setSampleRate(audio_samplerate);
    202         pSoundStretch->setChannels(audio_channels);
     593        float laudio_stretchfactor = audio_stretchfactor;
     594        delete pSoundStretch;
     595        pSoundStretch = NULL;
     596        audio_stretchfactor = 0.0;
     597        SetStretchFactorLocked(laudio_stretchfactor);
    203598    }
     599    else
     600    {
     601        SetStretchFactorLocked(audio_stretchfactor);
     602        if (pSoundStretch)
     603        {
     604            // if its passthru then we need to reencode
     605            if (audio_codec)
     606            {
     607                if (!encoder)
     608                {
     609                    VERBOSE(VB_AUDIO, LOC + QString("Creating Encoder for codec %1").arg(audio_codec->codec_id));
     610                    encoder = new DigitalEncoder();
     611                    if (!encoder->Init(audio_codec->codec_id,
     612                                audio_codec->bit_rate,
     613                                audio_codec->sample_rate,
     614                                audio_codec->channels
     615                                ))
     616                    {
     617                        // eeks
     618                        delete encoder;
     619                        encoder = NULL;
     620                        VERBOSE(VB_AUDIO, LOC + QString("Failed to Create Encoder"));
     621                    }
     622                }
     623            }
     624            if (encoder)
     625            {
     626                pSoundStretch->setSampleRate(audio_codec->sample_rate);
     627                pSoundStretch->setChannels(audio_codec->channels);
     628            }
     629            else
     630            {
     631                pSoundStretch->setSampleRate(audio_samplerate);
     632                pSoundStretch->setChannels(audio_channels);
     633            }
     634        }
     635    }
    204636
    205637    // Setup visualisations, zero the visualisations buffers
    206638    prepareVisuals();
     
    246678        pSoundStretch = NULL;
    247679    }
    248680
     681    if (encoder)
     682    {
     683        delete encoder;
     684        encoder = NULL;
     685    }
     686
    249687    CloseDevice();
    250688
    251689    killAudioLock.unlock();
     
    259697
    260698void AudioOutputBase::Pause(bool paused)
    261699{
     700    VERBOSE(VB_AUDIO, LOC+ QString("Pause %0").arg(paused));
    262701    pauseaudio = paused;
    263702    audio_actually_paused = false;
    264703}
     
    339778       The reason is that computing 'audiotime' requires acquiring the audio
    340779       lock, which the video thread should not do. So, we call 'SetAudioTime()'
    341780       from the audio thread, and then call this from the video thread. */
    342     int ret;
     781    long long ret;
    343782    struct timeval now;
    344783
    345784    if (audiotime == 0)
     
    351790
    352791    ret = (now.tv_sec - audiotime_updated.tv_sec) * 1000;
    353792    ret += (now.tv_usec - audiotime_updated.tv_usec) / 1000;
    354     ret = (int)(ret * audio_stretchfactor);
     793    ret = (long long)(ret * audio_stretchfactor);
    355794
     795#if 1
     796    VERBOSE(VB_AUDIO|VB_TIMESTAMP,
     797            QString("GetAudiotime now=%1.%2, set=%3.%4, ret=%5, audt=%6 sf=%7")
     798            .arg(now.tv_sec).arg(now.tv_usec)
     799            .arg(audiotime_updated.tv_sec).arg(audiotime_updated.tv_usec)
     800            .arg(ret)
     801            .arg(audiotime)
     802            .arg(audio_stretchfactor)
     803           );
     804#endif
     805
    356806    ret += audiotime;
    357807
    358808    pthread_mutex_unlock(&avsync_lock);
    359     return ret;
     809    return (int)ret;
    360810}
    361811
    362812void AudioOutputBase::SetAudiotime(void)
     
    393843    // include algorithmic latencies
    394844    if (pSoundStretch)
    395845    {
     846        // if encoder is active, then use its idea of audiobytes
     847        //size_t abps = encoder?encoder->audio_bytes_per_sample:audio_bytes_per_sample;
     848
     849        // add the effect of any unused but processed samples, AC3 reencode does this
     850        totalbuffer += (int)(pSoundStretch->numSamples() * audio_bytes_per_sample);
    396851        // add the effect of unprocessed samples in time stretch algo
    397852        totalbuffer += (int)((pSoundStretch->numUnprocessedSamples() *
    398853                              audio_bytes_per_sample) / audio_stretchfactor);
    399854    }
    400                
     855
    401856    audiotime = audbuf_timecode - (int)(totalbuffer * 100000.0 /
    402857                                   (audio_bytes_per_sample * effdspstretched));
    403858 
    404859    gettimeofday(&audiotime_updated, NULL);
     860#if 1
     861    VERBOSE(VB_AUDIO|VB_TIMESTAMP,
     862            QString("SetAudiotime set=%1.%2, audt=%3 atc=%4 tb=%5 sb=%6 eds=%7 abps=%8 sf=%9")
     863            .arg(audiotime_updated.tv_sec).arg(audiotime_updated.tv_usec)
     864            .arg(audiotime)
     865            .arg(audbuf_timecode)
     866            .arg(totalbuffer)
     867            .arg(soundcard_buffer)
     868            .arg(effdspstretched)
     869            .arg(audio_bytes_per_sample)
     870            .arg(audio_stretchfactor)
     871           );
     872#endif
    405873
    406874    pthread_mutex_unlock(&avsync_lock);
    407875    pthread_mutex_unlock(&audio_buflock);
     
    461929    // NOTE: This function is not threadsafe
    462930
    463931    int afree = audiofree(true);
    464     int len = samples * audio_bytes_per_sample;
     932    int len = samples * (encoder?encoder->audio_bytes_per_sample:audio_bytes_per_sample);
    465933
    466934    // Check we have enough space to write the data
    467935    if (need_resampler && src_ctx)
    468936        len = (int)ceilf(float(len) * src_data.src_ratio);
    469937    if ((len > afree) && !blocking)
     938    {
     939        VERBOSE(VB_AUDIO|VB_TIMESTAMP, QString("AddSamples FAILED bytes=%1, used=%2, free=%3, timecode=%4")
     940            .arg(len)
     941            .arg(AUDBUFSIZE-afree).arg(afree).arg(LONGLONGCONVERT timecode));
    470942        return false; // would overflow
     943    }
    471944
    472945    // resample input if necessary
    473946    if (need_resampler && src_ctx)
     
    501974
    502975int AudioOutputBase::WaitForFreeSpace(int samples)
    503976{
    504     int len = samples * audio_bytes_per_sample;
     977    int abps = encoder?encoder->audio_bytes_per_sample:audio_bytes_per_sample;
     978    int len = samples * abps;
    505979    int afree = audiofree(false);
    506980
    507981    while (len > afree)
    508982    {
    509983        if (blocking)
    510984        {
    511             VERBOSE(VB_AUDIO, "Waiting for free space");
     985            VERBOSE(VB_AUDIO|VB_TIMESTAMP, "Waiting for free space");
    512986            // wait for more space
    513987            pthread_cond_wait(&audio_bufsig, &audio_buflock);
    514988            afree = audiofree(false);
    515989        }
    516990        else
    517991        {
    518             VERBOSE(VB_IMPORTANT, "Audio buffer overflow, audio data lost!");
    519             samples = afree / audio_bytes_per_sample;
    520             len = samples * audio_bytes_per_sample;
     992            VERBOSE(VB_IMPORTANT,
     993                    QString("Audio buffer overflow, %1 audio samples lost!")
     994                        .arg(samples-afree / abps));
     995            samples = afree / abps;
     996            len = samples * abps;
    521997            if (src_ctx)
    522998            {
    523999                int error = src_reset(src_ctx);
     
    5421018   
    5431019    int afree = audiofree(false);
    5441020
    545     VERBOSE(VB_AUDIO, QString("_AddSamples bytes=%1, used=%2, free=%3, timecode=%4")
    546             .arg(samples * audio_bytes_per_sample)
    547             .arg(AUDBUFSIZE-afree).arg(afree).arg((long)timecode));
     1021    int abps = encoder?encoder->audio_bytes_per_sample:audio_bytes_per_sample;
     1022    VERBOSE(VB_AUDIO|VB_TIMESTAMP, QString("_AddSamples samples=%1 bytes=%2, used=%3, free=%4, timecode=%5")
     1023            .arg(samples)
     1024            .arg(samples * abps)
     1025            .arg(AUDBUFSIZE-afree).arg(afree).arg(LONGLONGCONVERT timecode));
    5481026   
    5491027    len = WaitForFreeSpace(samples);
    5501028
     
    5811059
    5821060    if (pSoundStretch)
    5831061    {
     1062
    5841063        // does not change the timecode, only the number of samples
    5851064        // back to orig pos
    5861065        org_waud = waud;
    5871066        int bdiff = AUDBUFSIZE - org_waud;
    588         int nSamplesToEnd = bdiff/audio_bytes_per_sample;
     1067        int nSamplesToEnd = bdiff/abps;
    5891068        if (bdiff < len)
    5901069        {
    5911070            pSoundStretch->putSamples((soundtouch::SAMPLETYPE*)(audiobuffer +
    5921071                                      org_waud), nSamplesToEnd);
    5931072            pSoundStretch->putSamples((soundtouch::SAMPLETYPE*)audiobuffer,
    594                                       (len - bdiff) / audio_bytes_per_sample);
     1073                                      (len - bdiff) / abps);
    5951074        }
    5961075        else
    5971076        {
    5981077            pSoundStretch->putSamples((soundtouch::SAMPLETYPE*)(audiobuffer +
    599                                       org_waud), len / audio_bytes_per_sample);
     1078                                      org_waud), len / abps);
    6001079        }
    6011080
    602         int newLen = 0;
    603         int nSamples;
    604         len = WaitForFreeSpace(pSoundStretch->numSamples() *
    605                                audio_bytes_per_sample);
    606         do
     1081        if (encoder)
    6071082        {
    608             int samplesToGet = len/audio_bytes_per_sample;
    609             if (samplesToGet > nSamplesToEnd)
     1083            // pull out a packet's worth and reencode it until we dont have enough
     1084            // for any more packets
     1085            soundtouch::SAMPLETYPE* temp_buff =
     1086                (soundtouch::SAMPLETYPE*)encoder->GetFrameBuffer();
     1087            size_t frameSize = encoder->FrameSize()/abps;
     1088            VERBOSE(VB_AUDIO|VB_TIMESTAMP,
     1089                    QString("_AddSamples Enc sfs=%1 bfs=%2 sss=%3")
     1090                    .arg(frameSize)
     1091                    .arg(encoder->FrameSize())
     1092                    .arg(pSoundStretch->numSamples())
     1093                   );
     1094            // process the same number of samples as it creates a full encoded buffer
     1095            // just like before
     1096            while (pSoundStretch->numSamples() >= frameSize)
    6101097            {
    611                 samplesToGet = nSamplesToEnd;   
     1098                int got = pSoundStretch->receiveSamples(temp_buff, frameSize);
     1099                int amount = encoder->Encode(temp_buff);
     1100                VERBOSE(VB_AUDIO|VB_TIMESTAMP,
     1101                        QString("_AddSamples Enc bytes=%1 got=%2 left=%3")
     1102                        .arg(amount)
     1103                        .arg(got)
     1104                        .arg(pSoundStretch->numSamples())
     1105                       );
     1106                if (amount == 0)
     1107                    continue;
     1108                //len = WaitForFreeSpace(amount);
     1109                char * ob = encoder->GetOutBuff();
     1110                if (amount >= bdiff)
     1111                {
     1112                    memcpy(audiobuffer + org_waud, ob, bdiff);
     1113                    ob += bdiff;
     1114                    amount -= bdiff;
     1115                    org_waud = 0;
     1116                }
     1117                if (amount > 0)
     1118                    memcpy(audiobuffer + org_waud, ob, amount);
     1119                bdiff = AUDBUFSIZE - amount;
     1120                org_waud += amount;
    6121121            }
    613 
    614             nSamples = pSoundStretch->receiveSamples((soundtouch::SAMPLETYPE*)
    615                                       (audiobuffer + org_waud), samplesToGet);
    616             if (nSamples == nSamplesToEnd)
     1122        }
     1123        else
     1124        {
     1125            int newLen = 0;
     1126            int nSamples;
     1127            len = WaitForFreeSpace(pSoundStretch->numSamples() *
     1128                                   audio_bytes_per_sample);
     1129            do
    6171130            {
    618                 org_waud = 0;
    619                 nSamplesToEnd = AUDBUFSIZE/audio_bytes_per_sample;
    620             }
    621             else
    622             {
    623                 org_waud += nSamples * audio_bytes_per_sample;
    624                 nSamplesToEnd -= nSamples;
    625             }
     1131                int samplesToGet = len/audio_bytes_per_sample;
     1132                if (samplesToGet > nSamplesToEnd)
     1133                {
     1134                    samplesToGet = nSamplesToEnd;   
     1135                }
    6261136
    627             newLen += nSamples * audio_bytes_per_sample;
    628             len -= nSamples * audio_bytes_per_sample;
    629         } while (nSamples > 0);
     1137                nSamples = pSoundStretch->receiveSamples((soundtouch::SAMPLETYPE*)
     1138                                          (audiobuffer + org_waud), samplesToGet);
     1139                if (nSamples == nSamplesToEnd)
     1140                {
     1141                    org_waud = 0;
     1142                    nSamplesToEnd = AUDBUFSIZE/audio_bytes_per_sample;
     1143                }
     1144                else
     1145                {
     1146                    org_waud += nSamples * audio_bytes_per_sample;
     1147                    nSamplesToEnd -= nSamples;
     1148                }
     1149
     1150                newLen += nSamples * audio_bytes_per_sample;
     1151                len -= nSamples * audio_bytes_per_sample;
     1152            } while (nSamples > 0);
     1153        }
    6301154    }
    6311155
    6321156    waud = org_waud;
     
    6961220            space_on_soundcard = getSpaceOnSoundcard();
    6971221
    6981222            if (space_on_soundcard != last_space_on_soundcard) {
    699                 VERBOSE(VB_AUDIO, QString("%1 bytes free on soundcard")
     1223                VERBOSE(VB_AUDIO|VB_TIMESTAMP, QString("%1 bytes free on soundcard")
    7001224                        .arg(space_on_soundcard));
    7011225                last_space_on_soundcard = space_on_soundcard;
    7021226            }
     
    7091233                    WriteAudio(zeros, fragment_size);
    7101234                } else {
    7111235                    // this should never happen now -dag
    712                     VERBOSE(VB_AUDIO,
     1236                    VERBOSE(VB_AUDIO|VB_TIMESTAMP,
    7131237                            QString("waiting for space on soundcard "
    7141238                                    "to write zeros: have %1 need %2")
    7151239                            .arg(space_on_soundcard).arg(fragment_size));
     
    7451269        if (fragment_size > audiolen(true))
    7461270        {
    7471271            if (audiolen(true) > 0)  // only log if we're sending some audio
    748                 VERBOSE(VB_AUDIO,
     1272                VERBOSE(VB_AUDIO|VB_TIMESTAMP,
    7491273                        QString("audio waiting for buffer to fill: "
    7501274                                "have %1 want %2")
    7511275                        .arg(audiolen(true)).arg(fragment_size));
    7521276
    753             VERBOSE(VB_AUDIO, "Broadcasting free space avail");
     1277            //VERBOSE(VB_AUDIO|VB_TIMESTAMP, "Broadcasting free space avail");
    7541278            pthread_mutex_lock(&audio_buflock);
    7551279            pthread_cond_broadcast(&audio_bufsig);
    7561280            pthread_mutex_unlock(&audio_buflock);
     
    7641288        if (fragment_size > space_on_soundcard)
    7651289        {
    7661290            if (space_on_soundcard != last_space_on_soundcard) {
    767                 VERBOSE(VB_AUDIO,
     1291                VERBOSE(VB_AUDIO|VB_TIMESTAMP,
    7681292                        QString("audio waiting for space on soundcard: "
    7691293                                "have %1 need %2")
    7701294                        .arg(space_on_soundcard).arg(fragment_size));
     
    8261350
    8271351        /* update raud */
    8281352        raud = (raud + fragment_size) % AUDBUFSIZE;
    829         VERBOSE(VB_AUDIO, "Broadcasting free space avail");
     1353        //VERBOSE(VB_AUDIO|VB_TIMESTAMP, "Broadcasting free space avail");
    8301354        pthread_cond_broadcast(&audio_bufsig);
    8311355
    8321356        written_size = fragment_size;
  • libs/libmyth/audiooutputalsa.cpp

     
    8282    }
    8383    else
    8484    {
    85         fragment_size = 6144; // nicely divisible by 2,4,6,8 channels @ 16-bits
    86         buffer_time = 500000;  // .5 seconds
     85        //fragment_size = 6144; // nicely divisible by 2,4,6,8 channels @ 16-bits
     86        //fragment_size = 3072*audio_channels; // nicely divisible by 2,4,6,8 channels @ 16-bits
     87        fragment_size = (audio_bits * audio_channels * audio_samplerate) / (8*30);
     88        buffer_time = 100000;  // .5 seconds
    8789        period_time = buffer_time / 4;  // 4 interrupts per buffer
    8890    }
    8991
     
    155157   
    156158    tmpbuf = aubuf;
    157159
    158     VERBOSE(VB_AUDIO, QString("WriteAudio: Preparing %1 bytes (%2 frames)")
     160    VERBOSE(VB_AUDIO|VB_TIMESTAMP, QString("WriteAudio: Preparing %1 bytes (%2 frames)")
    159161            .arg(size).arg(frames));
    160162   
    161163    while (frames > 0)
  • libs/libmythsoundtouch/TDStretch.cpp

     
    9696
    9797    pMidBuffer = NULL;
    9898    pRefMidBufferUnaligned = NULL;
     99    midBufferLength = 0;
    99100    overlapLength = 0;
    100101
    101102    setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
     
    108109
    109110TDStretch::~TDStretch()
    110111{
    111     delete[] pMidBuffer;
    112     delete[] pRefMidBufferUnaligned;
     112    if (midBufferLength)
     113    {
     114        delete[] pMidBuffer;
     115        delete[] pRefMidBufferUnaligned;
     116        midBufferLength = 0;
     117    }
    113118}
    114119
    115120
     
    196201
    197202void TDStretch::clearMidBuffer()
    198203{
    199     if (bMidBufferDirty)
     204    if (bMidBufferDirty && midBufferLength)
    200205    {
    201         memset(pMidBuffer, 0, 2 * sizeof(SAMPLETYPE) * overlapLength);
     206        memset(pMidBuffer, 0, channels * sizeof(SAMPLETYPE) * overlapLength);
    202207        bMidBufferDirty = FALSE;
    203208    }
    204209}
     
    239244// Seeks for the optimal overlap-mixing position.
    240245uint TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
    241246{
     247#ifdef MULTICHANNEL
     248    if (channels > 2)
     249    {
     250        // stereo sound
     251        if (bQuickseek)
     252        {
     253            return seekBestOverlapPositionMultiQuick(refPos);
     254        }
     255        else
     256        {
     257            return seekBestOverlapPositionMulti(refPos);
     258        }
     259    }
     260    else
     261#endif
    242262    if (channels == 2)
    243263    {
    244264        // stereo sound
     
    272292// of 'ovlPos'.
    273293inline void TDStretch::overlap(SAMPLETYPE *output, const SAMPLETYPE *input, uint ovlPos) const
    274294{
     295#ifdef MULTICHANNEL
     296    if (channels > 2)
     297    {
     298        overlapMulti(output, input + channels * ovlPos);
     299    }
     300    else
     301#endif
    275302    if (channels == 2)
    276303    {
    277304        // stereo sound
     
    285312
    286313
    287314
     315#ifdef MULTICHANNEL
    288316// Seeks for the optimal overlap-mixing position. The 'stereo' version of the
    289317// routine
    290318//
    291319// The best position is determined as the position where the two overlapped
    292320// sample sequences are 'most alike', in terms of the highest cross-correlation
    293321// value over the overlapping period
     322uint TDStretch::seekBestOverlapPositionMulti(const SAMPLETYPE *refPos)
     323{
     324    uint bestOffs;
     325    LONG_SAMPLETYPE bestCorr, corr;
     326    uint i;
     327
     328    // Slopes the amplitudes of the 'midBuffer' samples
     329    precalcCorrReference();
     330
     331    bestCorr = INT_MIN;
     332    bestOffs = 0;
     333
     334    // Scans for the best correlation value by testing each possible position
     335    // over the permitted range.
     336    for (i = 0; i < seekLength; i ++)
     337    {
     338        // Calculates correlation value for the mixing position corresponding
     339        // to 'i'
     340        corr = calcCrossCorrMulti(refPos + channels * i, pRefMidBuffer);
     341
     342        // Checks for the highest correlation value
     343        if (corr > bestCorr)
     344        {
     345            bestCorr = corr;
     346            bestOffs = i;
     347        }
     348    }
     349    // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
     350    clearCrossCorrState();
     351
     352    return bestOffs;
     353}
     354
     355
     356// Seeks for the optimal overlap-mixing position. The 'stereo' version of the
     357// routine
     358//
     359// The best position is determined as the position where the two overlapped
     360// sample sequences are 'most alike', in terms of the highest cross-correlation
     361// value over the overlapping period
     362uint TDStretch::seekBestOverlapPositionMultiQuick(const SAMPLETYPE *refPos)
     363{
     364    uint j;
     365    uint bestOffs;
     366    LONG_SAMPLETYPE bestCorr, corr;
     367    uint scanCount, corrOffset, tempOffset;
     368
     369    // Slopes the amplitude of the 'midBuffer' samples
     370    precalcCorrReference();
     371
     372    bestCorr = INT_MIN;
     373    bestOffs = 0;
     374    corrOffset = 0;
     375    tempOffset = 0;
     376
     377    // Scans for the best correlation value using four-pass hierarchical search.
     378    //
     379    // The look-up table 'scans' has hierarchical position adjusting steps.
     380    // In first pass the routine searhes for the highest correlation with
     381    // relatively coarse steps, then rescans the neighbourhood of the highest
     382    // correlation with better resolution and so on.
     383    for (scanCount = 0;scanCount < 4; scanCount ++)
     384    {
     385        j = 0;
     386        while (scanOffsets[scanCount][j])
     387        {
     388            tempOffset = corrOffset + scanOffsets[scanCount][j];
     389            if (tempOffset >= seekLength) break;
     390
     391            // Calculates correlation value for the mixing position corresponding
     392            // to 'tempOffset'
     393            corr = calcCrossCorrMulti(refPos + channels * tempOffset, pRefMidBuffer);
     394
     395            // Checks for the highest correlation value
     396            if (corr > bestCorr)
     397            {
     398                bestCorr = corr;
     399                bestOffs = tempOffset;
     400            }
     401            j ++;
     402        }
     403        corrOffset = bestOffs;
     404    }
     405    // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
     406    clearCrossCorrState();
     407
     408    return bestOffs;
     409}
     410#endif
     411
     412// Seeks for the optimal overlap-mixing position. The 'stereo' version of the
     413// routine
     414//
     415// The best position is determined as the position where the two overlapped
     416// sample sequences are 'most alike', in terms of the highest cross-correlation
     417// value over the overlapping period
    294418uint TDStretch::seekBestOverlapPositionStereo(const SAMPLETYPE *refPos)
    295419{
    296420    uint bestOffs;
     
    512636void TDStretch::setChannels(uint numChannels)
    513637{
    514638    if (channels == numChannels) return;
     639#ifdef MULTICHANNEL
     640    assert(numChannels >= 1 && numChannels <= MULTICHANNEL);
     641#else
    515642    assert(numChannels == 1 || numChannels == 2);
     643#endif
    516644
    517645    channels = numChannels;
    518646    inputBuffer.setChannels(channels);
     
    635763/// Set new overlap length parameter & reallocate RefMidBuffer if necessary.
    636764void TDStretch::acceptNewOverlapLength(uint newOverlapLength)
    637765{
    638     uint prevOvl;
    639 
    640     prevOvl = overlapLength;
    641766    overlapLength = newOverlapLength;
    642767
    643     if (overlapLength > prevOvl)
     768    if (overlapLength*channels > midBufferLength)
    644769    {
    645         delete[] pMidBuffer;
    646         delete[] pRefMidBufferUnaligned;
     770        if (midBufferLength)
     771        {
     772            delete[] pMidBuffer;
     773            delete[] pRefMidBufferUnaligned;
     774            midBufferLength = 0;
     775        }
    647776
    648         pMidBuffer = new SAMPLETYPE[overlapLength * 2];
     777        midBufferLength = overlapLength * channels;
     778        pMidBuffer = new SAMPLETYPE[midBufferLength];
    649779        bMidBufferDirty = TRUE;
    650780        clearMidBuffer();
    651781
    652         pRefMidBufferUnaligned = new SAMPLETYPE[2 * overlapLength + 16 / sizeof(SAMPLETYPE)];
     782        pRefMidBufferUnaligned = new SAMPLETYPE[midBufferLength + 16 / sizeof(SAMPLETYPE)];
    653783        // ensure that 'pRefMidBuffer' is aligned to 16 byte boundary for efficiency
    654784        pRefMidBuffer = (SAMPLETYPE *)((((ulong)pRefMidBufferUnaligned) + 15) & -16);
    655785    }
     
    718848
    719849#ifdef INTEGER_SAMPLES
    720850
     851#ifdef MULTICHANNEL
    721852// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
    722853// is faster to calculate
     854void TDStretch::precalcCorrReference()
     855{
     856    int i,j;
     857    int temp, temp2;
     858    short *src = pMidBuffer;
     859    short *dest = pRefMidBuffer;
     860
     861    for (i=0 ; i < (int)overlapLength ;i ++)
     862    {
     863        temp = i * (overlapLength - i);
     864
     865        for(j=0;j<channels;j++)
     866        {
     867            temp2 = (*src++ * temp) / slopingDivider;
     868            *dest++ = (short)(temp2);
     869        }
     870    }
     871}
     872#endif
     873
     874// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
     875// is faster to calculate
    723876void TDStretch::precalcCorrReferenceStereo()
    724877{
    725878    int i, cnt2;
     
    772925    }
    773926}
    774927
     928#ifdef MULTICHANNEL
     929// Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Stereo'
     930// version of the routine.
     931void TDStretch::overlapMulti(short *output, const short *input) const
     932{
     933    int i,j;
     934    short temp;
     935    //uint cnt2;
     936    const short *ip = input;
     937    short *op = output;
     938    const short *md = pMidBuffer;
    775939
     940    for (i = 0; i < (int)overlapLength ; i ++)
     941    {
     942        temp = (short)(overlapLength - i);
     943        for(j=0;j<channels;j++)
     944            *op++ = (*ip++ * i + *md++ * temp )  / overlapLength;
     945    }
     946}
     947#endif
     948
     949
    776950/// Calculates overlap period length in samples.
    777951/// Integer version rounds overlap length to closest power of 2
    778952/// for a divide scaling operation.
     
    824998    return corr;
    825999}
    8261000
     1001#ifdef MULTICHANNEL
     1002long TDStretch::calcCrossCorrMulti(const short *mixingPos, const short *compare) const
     1003{
     1004    long corr;
     1005    uint i;
     1006
     1007    corr = 0;
     1008    for (i = channels; i < channels * overlapLength; i++)
     1009    {
     1010        corr += (mixingPos[i] * compare[i]) >> overlapDividerBits;
     1011    }
     1012
     1013    return corr;
     1014}
     1015#endif
     1016
    8271017#endif // INTEGER_SAMPLES
    8281018
    8291019//////////////////////////////////////////////////////////////////////////////
     
    9311121    return corr;
    9321122}
    9331123
    934 #endif // FLOAT_SAMPLES
    935  No newline at end of file
     1124#endif // FLOAT_SAMPLES
  • libs/libmythsoundtouch/TDStretch.h

     
    4848#include "RateTransposer.h"
    4949#include "FIFOSamplePipe.h"
    5050
     51#ifdef MULTICHANNEL
     52#define USE_MULTI_MMX
     53#endif
     54
    5155namespace soundtouch
    5256{
    5357
     
    100104    SAMPLETYPE *pMidBuffer;
    101105    SAMPLETYPE *pRefMidBuffer;
    102106    SAMPLETYPE *pRefMidBufferUnaligned;
     107    uint midBufferLength;
    103108    uint overlapLength;
    104109    uint overlapDividerBits;
    105110    uint slopingDivider;
     
    123128    virtual void clearCrossCorrState();
    124129    void calculateOverlapLength(uint overlapMs);
    125130
     131#ifdef MULTICHANNEL
     132    virtual LONG_SAMPLETYPE calcCrossCorrMulti(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare) const;
     133#endif
    126134    virtual LONG_SAMPLETYPE calcCrossCorrStereo(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare) const;
    127135    virtual LONG_SAMPLETYPE calcCrossCorrMono(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare) const;
    128136
     137#ifdef MULTICHANNEL
     138    virtual uint seekBestOverlapPositionMulti(const SAMPLETYPE *refPos);
     139    virtual uint seekBestOverlapPositionMultiQuick(const SAMPLETYPE *refPos);
     140#endif
    129141    virtual uint seekBestOverlapPositionStereo(const SAMPLETYPE *refPos);
    130142    virtual uint seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos);
    131143    virtual uint seekBestOverlapPositionMono(const SAMPLETYPE *refPos);
    132144    virtual uint seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos);
    133145    uint seekBestOverlapPosition(const SAMPLETYPE *refPos);
    134146
     147#ifdef MULTICHANNEL
     148    virtual void overlapMulti(SAMPLETYPE *output, const SAMPLETYPE *input) const;
     149#endif
    135150    virtual void overlapStereo(SAMPLETYPE *output, const SAMPLETYPE *input) const;
    136151    virtual void overlapMono(SAMPLETYPE *output, const SAMPLETYPE *input) const;
    137152
    138153    void clearMidBuffer();
    139154    void overlap(SAMPLETYPE *output, const SAMPLETYPE *input, uint ovlPos) const;
    140155
     156#ifdef MULTICHANNEL
     157    void precalcCorrReference();
     158#endif
    141159    void precalcCorrReferenceMono();
    142160    void precalcCorrReferenceStereo();
    143161
     
    225243    class TDStretchMMX : public TDStretch
    226244    {
    227245    protected:
     246#ifdef USE_MULTI_MMX
     247#ifdef MULTICHANNEL
     248        long calcCrossCorrMulti(const short *mixingPos, const short *compare) const;
     249#endif
     250#endif
    228251        long calcCrossCorrStereo(const short *mixingPos, const short *compare) const;
    229252        virtual void overlapStereo(short *output, const short *input) const;
    230253        virtual void clearCrossCorrState();
     
    237260    class TDStretch3DNow : public TDStretch
    238261    {
    239262    protected:
     263#ifdef MULTICHANNEL
     264        //double calcCrossCorrMulti(const float *mixingPos, const float *compare) const;
     265#endif
    240266        double calcCrossCorrStereo(const float *mixingPos, const float *compare) const;
    241267    };
    242268#endif /// ALLOW_3DNOW
     
    247273    class TDStretchSSE : public TDStretch
    248274    {
    249275    protected:
     276#ifdef MULTICHANNEL
     277        //double calcCrossCorrMulti(const float *mixingPos, const float *compare) const;
     278#endif
    250279        double calcCrossCorrStereo(const float *mixingPos, const float *compare) const;
    251280    };
    252281
  • libs/libmythsoundtouch/RateTransposer.cpp

     
    330330{
    331331    if (uChannels == numchannels) return;
    332332
     333#ifdef MULTICHANNEL
     334    assert(numchannels >= 1 && numchannels <= MULTICHANNEL);
     335#else
    333336    assert(numchannels == 1 || numchannels == 2);
     337#endif
    334338    uChannels = numchannels;
    335339
    336340    storeBuffer.setChannels(uChannels);
  • libs/libmythsoundtouch/mmx_gcc.cpp

     
    141141    return tmp;
    142142}
    143143
     144#ifdef USE_MULTI_MMX
     145// Calculates cross correlation of two buffers
     146long TDStretchMMX::calcCrossCorrMulti(const short *pV1, const short *pV2) const
     147{
     148    //static const unsigned long long int mm_half __attribute__ ((aligned(8))) = 0xffffffffULL;
     149    static const __m64 mm_mask[4][8] __attribute__ ((aligned(8))) = {
     150        {
     151            // even bit
     152            0xffffffffffffffffULL,
     153            0xffffffffffffffffULL,
     154            0xffffffffffffffffULL,
     155            0xffffffffffffffffULL,
     156            0,
     157            0,
     158            0,
     159            0
     160        },
     161        {
     162            0xffffffffffffffffULL,
     163            0xffffffffffffffffULL,
     164            0xffffffffffffffffULL,
     165            0x0000ffffffffffffULL,
     166            0,
     167            0,
     168            0,
     169            0
     170        },
     171        {
     172            0xffffffffffffffffULL,
     173            0xffffffffffffffffULL,
     174            0xffffffffffffffffULL,
     175            0x00000000ffffffffULL,
     176            0,
     177            0,
     178            0,
     179            0
     180        },
     181        {
     182            0xffffffffffffffffULL,
     183            0xffffffffffffffffULL,
     184            0xffffffffffffffffULL,
     185            0x000000000000ffffULL,
     186            0,
     187            0,
     188            0,
     189            0
     190        }
     191    };
     192    uint tmp;
     193    uint adjustedOverlapLength = overlapLength*channels;
     194    uint counter = ((adjustedOverlapLength+15)>>4)-1;    // load counter to counter = overlapLength / 8 - 1
     195    uint remainder = (16-adjustedOverlapLength)&0xf;     // since there are 1/3 sample per 1/2 quadword
     196
     197    __m64 *ph = (__m64*)&mm_mask[remainder&3][remainder>>2];
     198    __m64 *pv1=(__m64*)pV1, *pv2=(__m64*)pV2;
     199    GI(__m64 m0, m1, m2, m3, m4, m5, m6); // temporaries
     200    uint shift = overlapDividerBits;
     201
     202    // prepare to the first round by loading
     203    SI(m1 = pv1[0],             movq_a2r(0, pv1, mm1)); // load m1 = pv1[0]
     204    SI(m2 = pv1[1],             movq_a2r(8, pv1, mm2)); // load m2 = pv1[1]
     205    SI(m0 = _mm_setzero_si64(), pxor_r2r(mm0, mm0));    // clear m0
     206    SI(m5 = _mm_cvtsi32_si64(shift),movd_v2r(shift, mm5));   // shift in 64bit reg
     207
     208    do {
     209        // Calculate cross-correlation between the tempOffset and tmpbid_buffer.
     210        // Process 4 parallel batches of 2 * stereo samples each during one
     211        // round to improve CPU-level parallellization.
     212        SI(m1 = _mm_madd_pi16(m1, pv2[0]),pmaddwd_a2r(0, pv2, mm1)); // multiply-add m1 = m1 * pv2[0]
     213        SI(m3 = pv1[2],                   movq_a2r(16, pv1, mm3));   // load mm3 = pv1[2]
     214        SI(m2 = _mm_madd_pi16(m2, pv2[1]),pmaddwd_a2r(8, pv2, mm2)); // multiply-add m2 = m2 * pv2[1]
     215        SI(m4 = pv1[3],                   movq_a2r(24, pv1, mm4));   // load mm4 = pv1[3]
     216        SI(m3 = _mm_madd_pi16(m3, pv2[2]),pmaddwd_a2r(16, pv2, mm3));// multiply-add m3 = m3 * pv2[2]
     217        SI(m2 = _mm_add_pi32(m2, m1),     paddd_r2r(mm1, mm2));      // add m2 += m1
     218        SI(m4 = _mm_madd_pi16(m4, pv2[3]),pmaddwd_a2r(24, pv2, mm4));// multiply-add m4 = m4 * pv2[3]
     219        SI(m1 = pv1[4],                   movq_a2r(32, pv1, mm1));   // mm1 = pv1[0] for next round
     220        SI(m2 = _mm_srai_pi32(m2, m5),    psrad_r2r(mm5, mm2));      // m2 >>= shift (mm5)
     221        pv1 += 4;                                                    // increment first pointer
     222        SI(m3 = _mm_add_pi32(m3, m4),     paddd_r2r(mm4, mm3));      // m3 += m4
     223        SI(m0 = _mm_add_pi32(m0, m2),     paddd_r2r(mm2, mm0));      // m0 += m2
     224        SI(m2 = pv1[1],                   movq_a2r(8, pv1, mm2));    // mm2 = pv1[1] for next round
     225        SI(m3 = _mm_srai_pi32(m3, m5),    psrad_r2r(mm5, mm3));    // m3 >>= shift (mm5)
     226        pv2 += 4;                                                    // increment second pointer
     227        SI(m0 = _mm_add_pi32(m0, m3),     paddd_r2r(mm3, mm0));      // add m0 += m3
     228    } while ((--counter)!=0);
     229
     230    SI(m6 = ph[0], movq_a2r(0, ph, mm6));
     231    // Finalize the last partial loop:
     232    SI(m1 = _mm_madd_pi16(m1, pv2[0]), pmaddwd_a2r(0, pv2, mm1));
     233    SI(m1 = _mm_and_si64(m1, m6),      pand_r2r(mm6, mm1));
     234    SI(m3 = pv1[2],                    movq_a2r(16, pv1, mm3));
     235    SI(m6 = ph[1], movq_a2r(8, ph, mm6));
     236    SI(m2 = _mm_madd_pi16(m2, pv2[1]), pmaddwd_a2r(8, pv2, mm2));
     237    SI(m2 = _mm_and_si64(m2, m6),      pand_r2r(mm6, mm2));
     238    SI(m4 = pv1[3],                    movq_a2r(24, pv1, mm4));
     239    SI(m6 = ph[2], movq_a2r(16, ph, mm6));
     240    SI(m3 = _mm_madd_pi16(m3, pv2[2]), pmaddwd_a2r(16, pv2, mm3));
     241    SI(m3 = _mm_and_si64(m3, m6),      pand_r2r(mm6, mm3));
     242    SI(m2 = _mm_add_pi32(m2, m1),      paddd_r2r(mm1, mm2));
     243    SI(m6 = ph[3], movq_a2r(24, ph, mm6));
     244    SI(m4 = _mm_madd_pi16(m4, pv2[3]), pmaddwd_a2r(24, pv2, mm4));
     245    SI(m4 = _mm_and_si64(m4, m6),      pand_r2r(mm6, mm4));
     246    SI(m2 = _mm_srai_pi32(m2, m5),     psrad_r2r(mm5, mm2));
     247    SI(m3 = _mm_add_pi32(m3, m4),      paddd_r2r(mm4, mm3));
     248    SI(m0 = _mm_add_pi32(m0, m2),      paddd_r2r(mm2, mm0));
     249    SI(m3 = _mm_srai_pi32(m3, m5),     psrad_r2r(mm5, mm3));
     250    SI(m0 = _mm_add_pi32(m0, m3),      paddd_r2r(mm3, mm0));
     251
     252    // copy hi-dword of mm0 to lo-dword of mm1, then sum mm0+mm1
     253    // and finally return the result
     254    SI(m1 = m0,                        movq_r2r(mm0, mm1));
     255    SI(m1 = _mm_srli_si64(m1, 32),     psrld_i2r(32, mm1));
     256    SI(m0 = _mm_add_pi32(m0, m1),      paddd_r2r(mm1, mm0));
     257    SI(tmp = _mm_cvtsi64_si32(m0),     movd_r2m(mm0, tmp));
     258    return tmp;
     259}
     260#endif
     261
    144262void TDStretchMMX::clearCrossCorrState()
    145263{
    146264    _mm_empty();
     
    224342    _mm_empty();
    225343}
    226344
     345#if 0
     346// MMX-optimized version of the function overlapMulti
     347void TDStretchMMX::overlapMulti(short *output, const short *input) const
     348{
     349    _mm_empty();
     350    uint shift = overlapDividerBits;
     351    uint counter = overlapLength>>2;                 // counter = overlapLength / 4
     352    __m64 *inPtr = (__m64*) input;                   // load address of inputBuffer
     353    __m64 *midPtr = (__m64*) pMidBuffer;             // load address of midBuffer
     354    __m64 *outPtr = ((__m64*) output)-2;             // load address of outputBuffer
     355    GI(__m64 m0, m1, m2, m3, m4, m5, m6, m7);        // temporaries
     356
     357    // load mixing value adder to mm5
     358    uint tmp0 = 0x0002fffe;                                      // tmp0 = 0x0002 fffe
     359    SI(m5 = _mm_cvtsi32_si64(tmp0),    movd_v2r(tmp0, mm5));     // mm5 = 0x0000 0000 0002 fffe
     360    SI(m5 = _mm_unpacklo_pi32(m5,m5),  punpckldq_r2r(mm5, mm5)); // mm5 = 0x0002 fffe 0002 fffe
     361    // load sliding mixing value counter to mm6
     362    SI(m6 = _mm_cvtsi32_si64(overlapLength), movd_v2r(overlapLength, mm6));
     363    SI(m6 = _mm_unpacklo_pi32(m6, m6), punpckldq_r2r(mm6, mm6)); // mm6 = 0x0000 OVL_ 0000 OVL_
     364    // load sliding mixing value counter to mm7
     365    uint tmp1 = (overlapLength-1)|0x00010000;                    // tmp1 = 0x0001 overlapLength-1
     366    SI(m7 = _mm_cvtsi32_si64(tmp1),    movd_v2r(tmp1, mm7));     // mm7 = 0x0000 0000 0001 01ff
     367    SI(m7 = _mm_unpacklo_pi32(m7, m7), punpckldq_r2r(mm7, mm7)); // mm7 = 0x0001 01ff 0001 01ff
     368
     369    do {
     370        // Process two parallel batches of 2+2 stereo samples during each round
     371        // to improve CPU-level parallellization.
     372        //
     373        // Load [midPtr] into m0 and m1
     374        // Load [inPtr] into m3
     375        // unpack words of m0, m1 and m3 into m0 and m1
     376        // multiply-add m0*m6 and m1*m7, store results into m0 and m1
     377        // divide m0 and m1 by 512 (=right-shift by overlapDividerBits)
     378        // pack the result into m0 and store into [edx]
     379        //
     380        // Load [midPtr+8] into m2 and m3
     381        // Load [inPtr+8] into m4
     382        // unpack words of m2, m3 and m4 into m2 and m3
     383        // multiply-add m2*m6 and m3*m7, store results into m2 and m3
     384        // divide m2 and m3 by 512 (=right-shift by overlapDividerBits)
     385        // pack the result into m2 and store into [edx+8]
     386        SI(m0 = midPtr[0],                movq_a2r(0, midPtr, mm0));// mm0 = m1l m1r m0l m0r
     387        outPtr += 2;
     388        SI(m3 = inPtr[0],                 movq_a2r(0, inPtr, mm3)); // mm3 = i1l i1r i0l i0r
     389        SI(m1 = m0,                       movq_r2r(mm0, mm1));      // mm1 = m1l m1r m0l m0r
     390        SI(m2 = midPtr[1],                movq_a2r(8, midPtr, mm2));// mm2 = m3l m3r m2l m2r
     391        SI(m0 = _mm_unpacklo_pi16(m0, m3),punpcklwd_r2r(mm3, mm0)); // mm0 = i0l m0l i0r m0r
     392        midPtr += 2;
     393        SI(m4 = inPtr[1],                 movq_a2r(8, inPtr, mm4)); // mm4 = i3l i3r i2l i2r
     394        SI(m1 = _mm_unpackhi_pi16(m1, m3),punpckhwd_r2r(mm3, mm1)); // mm1 = i1l m1l i1r m1r
     395        inPtr+=2;
     396        SI(m3 = m2,                       movq_r2r(mm2, mm3));      // mm3 = m3l m3r m2l m2r
     397        SI(m2 = _mm_unpacklo_pi16(m2, m4),punpcklwd_r2r(mm4, mm2)); // mm2 = i2l m2l i2r m2r
     398        // mm0 = i0l*m63+m0l*m62 i0r*m61+m0r*m60
     399        SI(m0 = _mm_madd_pi16(m0, m6),    pmaddwd_r2r(mm6, mm0));
     400        SI(m3 = _mm_unpackhi_pi16(m3, m4),punpckhwd_r2r(mm4, mm3)); // mm3 = i3l m3l i3r m3r
     401        SI(m4 = _mm_cvtsi32_si64(shift),  movd_v2r(shift, mm4));    // mm4 = shift
     402        // mm1 = i1l*m73+m1l*m72 i1r*m71+m1r*m70
     403        SI(m1 = _mm_madd_pi16(m1, m7),    pmaddwd_r2r(mm7, mm1));
     404        SI(m6 = _mm_add_pi16(m6, m5),     paddw_r2r(mm5, mm6));
     405        SI(m7 = _mm_add_pi16(m7, m5),     paddw_r2r(mm5, mm7));
     406        SI(m0 = _mm_srai_pi32(m0, m4),    psrad_r2r(mm4, mm0));    // mm0 >>= shift
     407        // mm2 = i2l*m63+m2l*m62 i2r*m61+m2r*m60
     408        SI(m2 = _mm_madd_pi16(m2, m6),    pmaddwd_r2r(mm6, mm2));
     409        SI(m1 = _mm_srai_pi32(m1, m4),    psrad_r2r(mm4, mm1));    // mm1 >>= shift
     410        // mm3 = i3l*m73+m3l*m72 i3r*m71+m3r*m70
     411        SI(m3 = _mm_madd_pi16(m3, m7),    pmaddwd_r2r(mm7, mm3));
     412        SI(m2 = _mm_srai_pi32(m2, m4),    psrad_r2r(mm4, mm2));    // mm2 >>= shift
     413        SI(m0 = _mm_packs_pi32(m0, m1),   packssdw_r2r(mm1, mm0)); // mm0 = mm1h mm1l mm0h mm0l
     414        SI(m3 = _mm_srai_pi32(m3, m4),    psrad_r2r(mm4, mm3));    // mm3 >>= shift
     415        SI(m6 = _mm_add_pi16(m6, m5),     paddw_r2r(mm5, mm6));
     416        SI(m2 = _mm_packs_pi32(m2, m3),   packssdw_r2r(mm3, mm2)); // mm2 = mm2h mm2l mm3h mm3l
     417        SI(m7 = _mm_add_pi16(m7, m5),     paddw_r2r(mm5, mm7));
     418        SI(outPtr[0] = m0,                movq_r2a(mm0, 0, outPtr));
     419        SI(outPtr[1] = m2,                movq_r2a(mm2, 8, outPtr));
     420    } while ((--counter)!=0);
     421    _mm_empty();
     422}
     423#endif
     424
    227425//////////////////////////////////////////////////////////////////////////////
    228426//
    229427// implementation of MMX optimized functions of class 'FIRFilter'
  • libs/libmythsoundtouch/STTypes.h

     
    6161    #define INTEGER_SAMPLES       //< 16bit integer samples
    6262    //#define FLOAT_SAMPLES       //< 32bit float samples
    6363
     64    #define MULTICHANNEL 6
    6465
    6566    /// Define this to allow CPU-specific assembler optimizations. Notice that
    6667    /// having this enabled on non-x86 platforms doesn't matter; the compiler can
  • libs/libmythsoundtouch/SoundTouch.cpp

     
    140140// Sets the number of channels, 1 = mono, 2 = stereo
    141141void SoundTouch::setChannels(uint numChannels)
    142142{
     143#ifdef MULTICHANNEL
     144    if (numChannels < 1 || numChannels > MULTICHANNEL)
     145#else
    143146    if (numChannels != 1 && numChannels != 2)
     147#endif
    144148    {
    145149        throw std::runtime_error("Illegal number of channels");
    146150    }
  • programs/mythfrontend/globalsettings.cpp

     
    3636        dev.setNameFilter("adsp*");
    3737        gc->fillSelectionsFromDir(dev);
    3838    }
     39#ifdef USE_ALSA
     40    gc->addSelection("ALSA:default", "ALSA:default");
     41    gc->addSelection("ALSA:analog", "ALSA:analog");
     42    gc->addSelection("ALSA:digital", "ALSA:digital");
     43    gc->addSelection("ALSA:mixed-analog", "ALSA:mixed-analog");
     44    gc->addSelection("ALSA:mixed-digital", "ALSA:mixed-digital");
     45#endif
     46#ifdef USE_ARTS
     47    gc->addSelection("ARTS:", "ARTS:");
     48#endif
     49#ifdef USE_JACK
     50    gc->addSelection("JACK:output", "JACK:output");
     51#endif
     52    gc->addSelection("NULL", "NULL");
    3953
    4054    return gc;
    4155}
    4256
     57static HostComboBox *MaxAudioChannels()
     58{
     59    HostComboBox *gc = new HostComboBox("MaxChannels",false);
     60    gc->setLabel(QObject::tr("Max Audio Channels"));
     61    //gc->addSelection(QObject::tr("Mono"), "1");
     62    //gc->addSelection(QObject::tr("Stereo L+R"), "2", true); // default
     63    //gc->addSelection(QObject::tr("3 Channel: L C R"), "3");
     64    //gc->addSelection(QObject::tr("4 Channel: L R LS RS"), "4");
     65    //gc->addSelection(QObject::tr("5 Channel: L C R LS RS"), "5");
     66    //gc->addSelection(QObject::tr("6 Channel: L C R LS RS LFE"), "6");
     67    gc->addSelection(QObject::tr("Stereo"), "2", true); // default
     68    gc->addSelection(QObject::tr("6 Channel"), "6");
     69    gc->setHelpText(
     70            QObject::tr("Set the maximum number of audio channels to be decoded. "
     71                "This is for multi-channel/surround audio playback."));
     72    return gc;
     73}
     74
    4375static HostCheckBox *MythControlsVolume()
    4476{
    4577    HostCheckBox *gc = new HostCheckBox("MythControlsVolume");
     
    21252157         setUseLabel(false);
    21262158
    21272159         addChild(AudioOutputDevice());
     2160#if 0
     2161         ConfigurationGroup *hg = new HorizontalConfigurationGroup(false, false);
     2162         ConfigurationGroup* settingsLeft = new VerticalConfigurationGroup(false,false);
     2163         settingsLeft->addChild(AC3PassThrough());
     2164#ifdef CONFIG_DTS
     2165         settingsLeft->addChild(DTSPassThrough());
     2166#endif
     2167         settingsLeft->addChild(AggressiveBuffer());
     2168         hg->addChild(settingsLeft);
     2169
     2170         ConfigurationGroup* settingsRight = new VerticalConfigurationGroup(false,false);
     2171         settingsRight->addChild(MaxAudioChannels());
     2172         hg->addChild(settingsRight);
     2173
     2174         addChild(hg);
     2175#else
    21282176         addChild(AC3PassThrough());
    21292177#ifdef CONFIG_DTS
    21302178         addChild(DTSPassThrough());
    21312179#endif
    21322180         addChild(AggressiveBuffer());
     2181         addChild(MaxAudioChannels());
     2182#endif
    21332183
    21342184         Setting* volumeControl = MythControlsVolume();
    21352185         addChild(volumeControl);
  • programs/mythtranscode/transcode.cpp

     
    4646
    4747    // reconfigure sound out for new params
    4848    virtual void Reconfigure(int audio_bits, int audio_channels,
    49                              int audio_samplerate, bool audio_passthru)
     49                             int audio_samplerate, bool audio_passthru,
     50                             void * = NULL)
    5051    {
     52        ClearError();
    5153        (void)audio_samplerate;
    5254        bits = audio_bits;
    5355        channels = audio_channels;
    5456        bytes_per_sample = bits * channels / 8;
     57        if (channels>2)
     58            Error("Invalid channel count");
    5559    }
    5660
    5761    // dsprate is in 100 * samples/second
  • libs/libmythtv/avformatdecoder.h

     
    243243    bool              allow_ac3_passthru;
    244244    bool              allow_dts_passthru;
    245245    bool              disable_passthru;
     246    int               max_channels;
    246247
    247248    AudioInfo         audioIn;
    248249    AudioInfo         audioOut;
  • libs/libmythtv/avformatdecoder.cpp

     
    3939#define MAX_AC3_FRAME_SIZE 6144
    4040
    4141/** Set to zero to allow any number of AC3 channels. */
     42#define MAXCHANNELSELECT 1
     43#if MAXCHANNELSELECT
     44#define MAX_OUTPUT_CHANNELS compiler error
     45#else
    4246#define MAX_OUTPUT_CHANNELS 2
     47#endif
    4348
    4449static int dts_syncinfo(uint8_t *indata_ptr, int *flags,
    4550                        int *sample_rate, int *bit_rate);
     
    290295#ifdef CONFIG_DTS
    291296    allow_dts_passthru = gContext->GetNumSetting("DTSPassThru", false);
    292297#endif
     298    max_channels = gContext->GetNumSetting("MaxChannels", 2);
    293299
    294300    audioIn.sample_size = -32; // force SetupAudioStream to run once
    295301    ttd = GetNVP()->GetTeletextDecoder();
     
    411417    framesPlayed = lastKey;
    412418    framesRead = lastKey;
    413419
     420    VERBOSE(VB_PLAYBACK, QString("AvFormatDecoder::DoFastForward newframe %5 frame %1 fps %2 ts %3 disc %4 cur_dts %6 adj %7 newts %8 fsa %9")
     421        .arg(desiredFrame)
     422        .arg(fps)
     423        .arg(ts)
     424        .arg(discardFrames)
     425        .arg(framesPlayed)
     426        .arg(st->cur_dts)
     427        .arg(adj_cur_dts)
     428        .arg(newts)
     429        .arg(frameseekadjust)
     430        );
     431
    414432    int normalframes = desiredFrame - framesPlayed;
    415433
     434#if 0
     435    if (!exactseeks)
     436        normalframes = 0;
     437#endif
     438
    416439    SeekReset(lastKey, normalframes, discardFrames, discardFrames);
    417440
    418441    if (discardFrames)
     
    781804
    782805    fmt->flags &= ~AVFMT_NOFILE;
    783806
     807#if 1
     808    if ((m_playbackinfo) || livetv || watchingrecording)
     809    {
     810        const char *name = ic->av_class->item_name(ic);
     811        VERBOSE(VB_GENERAL, QString("libavformat type %1").arg(name));
     812    }
     813#endif
     814 
     815    //struct timeval one, two, res;
     816    //gettimeofday(&one, NULL);
     817
    784818    if (!ringBuffer->isDVD())
    785819        av_estimate_timings(ic);
    786820
     
    791825    if (-1 == ret)
    792826        return ret;
    793827
     828    // make sure its at the real start due to av_find_stream_info reading
     829    ret = av_seek_frame(ic, -1, 0, AVSEEK_FLAG_BACKWARD);
     830    if (ret < 0)
     831        av_seek_frame(ic, -1, 0, AVSEEK_FLAG_BYTE);     // reposition to start of stream
     832
    794833    // Select some starting audio and subtitle tracks.
    795834    // TODO do we need this? They will be called by GetFrame() anyway...
    796835    autoSelectAudioTrack();
     
    813852    // If we don't have a position map, set up ffmpeg for seeking
    814853    if (!recordingHasPositionMap)
    815854    {
     855        const char *name = ic->av_class->item_name(ic);
    816856        VERBOSE(VB_PLAYBACK, LOC +
    817                 "Recording has no position -- using libavformat seeking.");
     857                QString("Recording has no position -- using libavformat seeking. %1").arg(name));
    818858        int64_t dur = ic->duration / (int64_t)AV_TIME_BASE;
    819859
    820860        if (dur > 0)
     
    859899            QString("Successfully opened decoder for file: "
    860900                    "\"%1\". novideo(%2)").arg(filename).arg(novideo));
    861901
     902    // set initial position correctly
     903    //DoFastForward(0, true);
     904
    862905    // Return true if recording has position map
    863906    return recordingHasPositionMap;
    864907}
     
    10961139                            <<") already open, leaving it alone.");
    10971140                }
    10981141                //assert(enc->codec_id);
     1142                VERBOSE(VB_GENERAL, QString("AVFD: codec %1 has %2 channels").arg(codec_id_string(enc->codec_id)).arg(enc->channels));
     1143#if 0
     1144                if (enc->channels > 2)
     1145                    enc->channels = 2;
     1146#endif
    10991147
     1148#if 0
    11001149                // HACK BEGIN REALLY UGLY HACK FOR DTS PASSTHRU
    11011150                if (enc->codec_id == CODEC_ID_DTS)
    11021151                {
     
    11051154                    // enc->bit_rate = what??;
    11061155                }
    11071156                // HACK END REALLY UGLY HACK FOR DTS PASSTHRU
     1157#endif
    11081158
    11091159                bitrate += enc->bit_rate;
    11101160                break;
     
    16051655        {
    16061656            long long startpos = pkt->pos;
    16071657
    1608             VERBOSE(VB_PLAYBACK, LOC +
     1658            VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC +
    16091659                    QString("positionMap[ %1 ] == %2.")
    16101660                    .arg(prevgoppos / keyframedist)
    16111661                    .arg((int)startpos));
     
    23642414
    23652415        AVStream *curstream = ic->streams[pkt->stream_index];
    23662416
     2417#if 0
     2418        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC + QString("timecode pts:%1 dts:%2 codec:%3")
     2419                .arg(pkt->pts)
     2420                .arg(pkt->dts)
     2421                .arg((curstream && curstream->codec)?curstream->codec->codec_type:-1)
     2422               );
     2423#endif
     2424
    23672425        if (pkt->dts != (int64_t)AV_NOPTS_VALUE)
    23682426            pts = (long long)(av_q2d(curstream->time_base) * pkt->dts * 1000);
    23692427
     
    24842542                    if (!curstream->codec->channels)
    24852543                    {
    24862544                        QMutexLocker locker(&avcodeclock);
     2545#if MAXCHANNELSELECT
     2546                        VERBOSE(VB_IMPORTANT, LOC + QString("Setting channels to %1").arg(audioOut.channels));
     2547                        curstream->codec->cqp = max_channels;
     2548                        curstream->codec->channels = audioOut.channels;
     2549#else
    24872550                        curstream->codec->channels = MAX_OUTPUT_CHANNELS;
     2551#endif
    24882552                        ret = avcodec_decode_audio(
    24892553                            curstream->codec, audioSamples,
    24902554                            &data_size, ptr, len);
     
    25352599                    {
    25362600                        AVCodecContext *ctx = curstream->codec;
    25372601
     2602#if MAXCHANNELSELECT
    25382603                        if ((ctx->channels == 0) ||
     2604                            (ctx->channels > audioOut.channels))
     2605                            ctx->channels = audioOut.channels;
     2606#else
     2607                        if ((ctx->channels == 0) ||
    25392608                            (ctx->channels > MAX_OUTPUT_CHANNELS))
    25402609                            ctx->channels = MAX_OUTPUT_CHANNELS;
     2610#endif
    25412611
    25422612                        ret = avcodec_decode_audio(
    25432613                            ctx, audioSamples, &data_size, ptr, len);
     
    25732643                                (curstream->codec->channels * 2) /
    25742644                                curstream->codec->sample_rate);
    25752645
     2646                    VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC + QString("audio timecode %1 %2 %3 %4")
     2647                            .arg(pkt->pts)
     2648                            .arg(pkt->dts)
     2649                            .arg(temppts).arg(lastapts));
    25762650                    GetNVP()->AddAudioData((char *)audioSamples, data_size,
    25772651                                           temppts);
    25782652
     
    26732747                    else
    26742748                        temppts = lastvpts;
    26752749
     2750                    VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC + QString("video timecode %1 %2 %3 %4")
     2751                            .arg(pkt->pts)
     2752                            .arg(pkt->dts)
     2753                            .arg(temppts).arg(lastvpts));
    26762754/* XXX: Broken.
    26772755                    if (mpa_pic.qscale_table != NULL && mpa_pic.qstride > 0 &&
    26782756                        context->height == picframe->height)
     
    27692847
    27702848void AvFormatDecoder::SetDisablePassThrough(bool disable)
    27712849{
     2850#if MAXCHANNELSELECT
     2851    // can only disable never reenable as once tiemstretch is on its on for the session
     2852    if (disable_passthru)
     2853        return;
     2854#endif
    27722855    if (selectedAudioStream.av_stream_index < 0)
    27732856    {
    27742857        disable_passthru = disable;
    27752858        return;
    27762859    }
    2777 
     2860 
    27782861    if (disable != disable_passthru)
    27792862    {
    27802863        disable_passthru = disable;
     
    28012884    AVCodecContext *codec_ctx = NULL;
    28022885    AudioInfo old_in  = audioIn;
    28032886    AudioInfo old_out = audioOut;
     2887    bool using_passthru = false;
    28042888
    28052889    if ((currentAudioTrack >= 0) &&
    28062890        (selectedAudioStream.av_stream_index <= ic->nb_streams) &&
     
    28082892    {
    28092893        assert(curstream);
    28102894        assert(curstream->codec);
    2811         codec_ctx = curstream->codec;       
     2895        codec_ctx = curstream->codec;
    28122896        bool do_ac3_passthru = (allow_ac3_passthru && !transcoding &&
    2813                                 !disable_passthru &&
    28142897                                (codec_ctx->codec_id == CODEC_ID_AC3));
    28152898        bool do_dts_passthru = (allow_dts_passthru && !transcoding &&
    2816                                 !disable_passthru &&
    28172899                                (codec_ctx->codec_id == CODEC_ID_DTS));
     2900        using_passthru = do_ac3_passthru || do_dts_passthru;
    28182901        info = AudioInfo(codec_ctx->codec_id,
    28192902                         codec_ctx->sample_rate, codec_ctx->channels,
    2820                          do_ac3_passthru || do_dts_passthru);
     2903                         using_passthru && !disable_passthru);
    28212904    }
    28222905
    28232906    if (info == audioIn)
    28242907        return false; // no change
    28252908
     2909    QString ptmsg = "";
     2910    if (using_passthru)
     2911    {
     2912        ptmsg = QString(" using passthru");
     2913    }
    28262914    VERBOSE(VB_AUDIO, LOC + "Initializing audio parms from " +
    2827             QString("audio track #%1").arg(currentAudioTrack+1));
     2915            QString("audio track #%1")
     2916                .arg(currentAudioTrack+1)
     2917            + ptmsg );
    28282918
    28292919    audioOut = audioIn = info;
     2920#if MAXCHANNELSELECT
     2921    if (using_passthru)
     2922#else
    28302923    if (audioIn.do_passthru)
     2924#endif
    28312925    {
    28322926        // A passthru stream looks like a 48KHz 2ch (@ 16bit) to the sound card
    2833         audioOut.channels    = 2;
    2834         audioOut.sample_rate = 48000;
    2835         audioOut.sample_size = 4;
     2927        AudioInfo digInfo = audioOut;
     2928        if (!disable_passthru)
     2929        {
     2930            digInfo.channels    = 2;
     2931            digInfo.sample_rate = 48000;
     2932            digInfo.sample_size = 4;
     2933        }
     2934        if (audioOut.channels > max_channels)
     2935        {
     2936            audioOut.channels = max_channels;
     2937            audioOut.sample_size = audioOut.channels * 2;
     2938            codec_ctx->channels = audioOut.channels;
     2939        }
     2940#if MAXCHANNELSELECT
     2941        VERBOSE(VB_AUDIO, LOC + "Audio format changed digital passthrough " +
     2942                QString("%1\n\t\t\tfrom %2 ; %3\n\t\t\tto   %4 ; %5")
     2943                .arg(digInfo.toString())
     2944                .arg(old_in.toString()).arg(old_out.toString())
     2945                .arg(audioIn.toString()).arg(audioOut.toString()));
     2946
     2947        if (digInfo.sample_rate > 0)
     2948            GetNVP()->SetEffDsp(digInfo.sample_rate * 100);
     2949
     2950        //GetNVP()->SetAudioParams(audioOut.bps(), audioOut.channels,
     2951        //                         audioOut.sample_rate);
     2952        GetNVP()->SetAudioParams(digInfo.bps(), digInfo.channels,
     2953                                 digInfo.sample_rate, audioIn.do_passthru);
     2954        // allow the audio stuff to reencode
     2955        GetNVP()->SetAudioCodec(codec_ctx);
     2956        GetNVP()->ReinitAudio();
     2957        return true;
     2958#endif
    28362959    }
     2960#if MAXCHANNELSELECT
    28372961    else
    28382962    {
     2963        if (audioOut.channels > max_channels)
     2964        {
     2965            audioOut.channels = max_channels;
     2966            audioOut.sample_size = audioOut.channels * 2;
     2967            codec_ctx->channels = audioOut.channels;
     2968        }
     2969    }
     2970    bool audiook;
     2971#if 0
     2972    do
     2973    {
     2974#endif
     2975#else
     2976    else
     2977    {
    28392978        if (audioOut.channels > MAX_OUTPUT_CHANNELS)
    28402979        {
    28412980            audioOut.channels = MAX_OUTPUT_CHANNELS;
     
    28432982            codec_ctx->channels = MAX_OUTPUT_CHANNELS;
    28442983        }
    28452984    }
     2985#endif
    28462986
    28472987    VERBOSE(VB_AUDIO, LOC + "Audio format changed " +
    28482988            QString("\n\t\t\tfrom %1 ; %2\n\t\t\tto   %3 ; %4")
     
    28552995    GetNVP()->SetAudioParams(audioOut.bps(), audioOut.channels,
    28562996                             audioOut.sample_rate,
    28572997                             audioIn.do_passthru);
    2858     GetNVP()->ReinitAudio();
     2998    // allow the audio stuff to reencode
     2999    GetNVP()->SetAudioCodec(using_passthru?codec_ctx:NULL);
     3000    QString errMsg = GetNVP()->ReinitAudio();
     3001#if MAXCHANNELSELECT
     3002        audiook = errMsg.isEmpty();
     3003#if 0
     3004        if (!audiook)
     3005        {
     3006            switch (audioOut.channels)
     3007            {
     3008#if 0
     3009                case 8:
     3010                    audioOut.channels = 6;
     3011                    break;
     3012#endif
     3013                case 6:
     3014#if 0
     3015                    audioOut.channels = 5;
     3016                    break;
     3017                case 5:
     3018                    audioOut.channels = 4;
     3019                    break;
     3020                case 4:
     3021                    audioOut.channels = 3;
     3022                    break;
     3023                case 3:
     3024#endif
     3025                    audioOut.channels = 2;
     3026                    break;
     3027#if 0
     3028                case 2:
     3029                    audioOut.channels = 1;
     3030                    break;
     3031#endif
     3032                default:
     3033                    // failed to reconfigure under any circumstances
     3034                    audiook = true;
     3035                    audioOut.channels = 0;
     3036                    break;
     3037            }
     3038            audioOut.sample_size = audioOut.channels * 2;
     3039            codec_ctx->channels = audioOut.channels;
     3040        }
     3041    } while (!audiook);
     3042#endif
     3043#endif
    28593044
    28603045    return true;
    28613046}
  • libs/libmythtv/NuppelVideoPlayer.h

     
    112112    void SetVideoParams(int w, int h, double fps, int keydist,
    113113                        float a = 1.33333, FrameScanType scan = kScan_Ignore);
    114114    void SetAudioParams(int bits, int channels, int samplerate, bool passthru);
     115    void SetAudioCodec(void *ac);
    115116    void SetEffDsp(int dsprate);
    116117    void SetFileLength(int total, int frames);
    117118    void Zoom(int direction);
     
    149150    bool    IsDecoderThreadAlive(void) const  { return decoder_thread_alive; }
    150151    bool    IsReallyNearEnd(void) const;
    151152    bool    IsNearEnd(long long framesRemaining = -1) const;
     153    float   GetAudioStretchFactor() { return audio_stretchfactor; }
    152154    bool    PlayingSlowForPrebuffer(void) const { return m_playing_slower; }
    153155    bool    HasAudioIn(void) const            { return !no_audio_in; }
    154156    bool    HasAudioOut(void) const           { return !no_audio_out; }
     
    178180    bool Play(float speed = 1.0, bool normal = true,
    179181              bool unpauseaudio = true);
    180182    bool GetPause(void) const;
     183    float GetNextPlaySpeed() { return next_play_speed; }
    181184
    182185    // Seek stuff
    183186    bool FastForward(float seconds);
     
    509512    int      audio_bits;
    510513    int      audio_samplerate;
    511514    float    audio_stretchfactor;
     515    void     *audio_codec;
    512516    bool     audio_passthru;
    513517
    514518    // Picture-in-Picture
  • libs/libmythtv/NuppelVideoPlayer.cpp

     
    126126      audioOutput(NULL),            audiodevice("/dev/dsp"),
    127127      audio_channels(2),            audio_bits(-1),
    128128      audio_samplerate(44100),      audio_stretchfactor(1.0f),
     129      audio_codec(NULL),
    129130      // Picture-in-Picture
    130131      pipplayer(NULL), setpipplayer(NULL), needsetpipplayer(false),
    131132      // Preview window support
     
    565566    if (audioOutput)
    566567    {
    567568        audioOutput->Reconfigure(audio_bits, audio_channels,
    568                                  audio_samplerate, audio_passthru);
     569                                 audio_samplerate, audio_passthru,
     570                                 audio_codec);
    569571        errMsg = audioOutput->GetError();
    570572        if (!errMsg.isEmpty())
    571573            audioOutput->SetStretchFactor(audio_stretchfactor);
     
    698700        {
    699701            VERBOSE(VB_IMPORTANT, "Video sync method can't support double "
    700702                    "framerate (refresh rate too low for bob deint)");
     703            //m_scan = kScan_Ignore;
     704            //m_can_double = false;
    701705            FallbackDeint();
    702706        }
    703707    }
     
    15671571    warpfactor_avg = (warpfactor + (warpfactor_avg * (WARPAVLEN - 1))) /
    15681572                      WARPAVLEN;
    15691573
    1570     //cerr << "Divergence: " << divergence << "  Rate: " << rate
    1571     //<< "  Warpfactor: " << warpfactor << "  warpfactor_avg: "
    1572     //<< warpfactor_avg << endl;
     1574#if 1
     1575    VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("A/V "
     1576        "Divergence: %1 "
     1577        "  Rate: %2"
     1578        "  Warpfactor: %3"
     1579        "  warpfactor_avg: %4")
     1580        .arg(divergence)
     1581        .arg(rate)
     1582        .arg(warpfactor)
     1583        .arg(warpfactor_avg)
     1584        );
     1585#endif
    15731586    return divergence;
    15741587}
    15751588
     
    16501663    if (diverge < -MAXDIVERGE)
    16511664    {
    16521665        // If video is way ahead of audio, adjust for it...
    1653         QString dbg = QString("Video is %1 frames ahead of audio, ")
     1666        QString dbg = QString("Audio is %1 frames ahead of video, ")
    16541667            .arg(-diverge);
    16551668
    16561669        // Reset A/V Sync
     
    16651678            // decoding; display the frame, but don't wait for A/V Sync.
    16661679            videoOutput->PrepareFrame(buffer, ps);
    16671680            videoOutput->Show(m_scan);
    1668             VERBOSE(VB_PLAYBACK, LOC + dbg + "skipping A/V wait.");
     1681            VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC + dbg + "skipping A/V wait.");
    16691682        }
    16701683        else
    16711684        {
    16721685            // If we are using software decoding, skip this frame altogether.
    1673             VERBOSE(VB_PLAYBACK, LOC + dbg + "dropping frame.");
     1686            VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC + dbg + "dropping frame.");
    16741687        }
    16751688    }
    16761689    else if (!using_null_videoout)
     
    16791692        if (buffer)
    16801693            videoOutput->PrepareFrame(buffer, ps);
    16811694
     1695        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2").arg(avsync_adjustment).arg(m_double_framerate));
    16821696        videosync->WaitForFrame(avsync_adjustment);
     1697        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show");
    16831698        if (!resetvideo)
    16841699            videoOutput->Show(m_scan);
    16851700
     
    16991714
    17001715            // Display the second field
    17011716            videosync->AdvanceTrigger();
    1702             videosync->WaitForFrame(0);
     1717            videosync->WaitForFrame(avsync_adjustment);
    17031718            if (!resetvideo)
    17041719                videoOutput->Show(kScan_Intr2ndField);
    17051720        }
     
    17111726
    17121727    if (output_jmeter && output_jmeter->RecordCycleTime())
    17131728    {
    1714         //cerr << "avsync_delay: " << avsync_delay / 1000
    1715         //     << ", avsync_avg: " << avsync_avg / 1000
    1716         //     << ", warpfactor: " << warpfactor
    1717         //     << ", warpfactor_avg: " << warpfactor_avg << endl;
     1729#if 1
     1730        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("A/V "
     1731            "avsync_delay: %1"
     1732            ", avsync_avg: %2"
     1733            ", warpfactor: %3"
     1734            ", warpfactor_avg: %4")
     1735                .arg(avsync_delay / 1000)
     1736                .arg(avsync_avg / 1000)
     1737                .arg(warpfactor)
     1738                .arg(warpfactor_avg));
     1739#endif
    17181740    }
    17191741
    17201742    videosync->AdvanceTrigger();
     
    17251747        // If audio is way ahead of video, adjust for it...
    17261748        // by cutting the frame rate in half for the length of this frame
    17271749
    1728         avsync_adjustment = frame_interval;
     1750        //avsync_adjustment = frame_interval;
     1751        avsync_adjustment = refreshrate;
    17291752        lastsync = true;
    1730         VERBOSE(VB_PLAYBACK, LOC +
    1731                 QString("Audio is %1 frames ahead of video,\n"
     1753        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC +
     1754                QString("Video is %1 frames ahead of audio,\n"
    17321755                        "\t\t\tdoubling video frame interval.").arg(diverge));
    17331756    }
    17341757
    17351758    if (audioOutput && normal_speed)
    17361759    {
    17371760        long long currentaudiotime = audioOutput->GetAudiotime();
    1738 #if 0
    1739         VERBOSE(VB_PLAYBACK, QString(
     1761#if 1
     1762        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString(
    17401763                    "A/V timecodes audio %1 video %2 frameinterval %3 "
    17411764                    "avdel %4 avg %5 tcoffset %6")
    17421765                .arg(currentaudiotime)
     
    20022025
    20032026    usevideotimebase = gContext->GetNumSetting("UseVideoTimebase", 0);
    20042027
    2005     if ((print_verbose_messages & VB_PLAYBACK) != 0)
     2028    if ((print_verbose_messages & VB_PLAYBACK|VB_TIMESTAMP) == (VB_PLAYBACK|VB_TIMESTAMP))
    20062029        output_jmeter = new Jitterometer("video_output", 100);
    20072030    else
    20082031        output_jmeter = NULL;
     
    20422065            {
    20432066                VERBOSE(VB_IMPORTANT, "Video sync method can't support double "
    20442067                        "framerate (refresh rate too low for bob deint)");
     2068                //m_scan = kScan_Ignore;
     2069                //m_can_double = false;
    20452070                FallbackDeint();
    20462071            }
    20472072        }
     
    28062831    audio_passthru = passthru;
    28072832}
    28082833
     2834void NuppelVideoPlayer::SetAudioCodec(void* ac)
     2835{
     2836    audio_codec = ac;
     2837}
     2838
    28092839void NuppelVideoPlayer::SetEffDsp(int dsprate)
    28102840{
    28112841    if (audioOutput)
     
    28502880        tc_avcheck_framecounter++;
    28512881        if (tc_avcheck_framecounter == 30)
    28522882        {
    2853 #define AUTO_RESYNC 1
     2883#define AUTO_RESYNC 0
    28542884#if AUTO_RESYNC
    28552885            // something's terribly, terribly wrong.
    28562886            if (tc_lastval[TC_AUDIO] < tc_lastval[TC_VIDEO] - 10000000 ||
  • libs/libavcodec/a52dec.c

     
    142142    }
    143143}
    144144
     145static inline int16_t convert (int32_t i)
     146{
     147    if (i > 0x43c07fff)
     148        return 32767;
     149    else if (i < 0x43bf8000)
     150        return -32768;
     151    else
     152        return i - 0x43c00000;
     153}
     154
     155void float2s16_2 (float * _f, int16_t * s16)
     156{
     157    int i;
     158    int32_t * f = (int32_t *) _f;
     159
     160    for (i = 0; i < 256; i++) {
     161        s16[2*i] = convert (f[i]);
     162        s16[2*i+1] = convert (f[i+256]);
     163    }
     164}
     165
     166void float2s16_4 (float * _f, int16_t * s16)
     167{
     168    int i;
     169    int32_t * f = (int32_t *) _f;
     170
     171    for (i = 0; i < 256; i++) {
     172        s16[4*i] = convert (f[i]);
     173        s16[4*i+1] = convert (f[i+256]);
     174        s16[4*i+2] = convert (f[i+512]);
     175        s16[4*i+3] = convert (f[i+768]);
     176    }
     177}
     178
     179void float2s16_5 (float * _f, int16_t * s16)
     180{
     181    int i;
     182    int32_t * f = (int32_t *) _f;
     183
     184    for (i = 0; i < 256; i++) {
     185        s16[5*i] = convert (f[i]);
     186        s16[5*i+1] = convert (f[i+256]);
     187        s16[5*i+2] = convert (f[i+512]);
     188        s16[5*i+3] = convert (f[i+768]);
     189        s16[5*i+4] = convert (f[i+1024]);
     190    }
     191}
     192
     193int channels_multi (int flags)
     194{
     195    if (flags & A52_LFE)
     196        return 6;
     197    else if (flags & 1) /* center channel */
     198        return 5;
     199    else if ((flags & A52_CHANNEL_MASK) == A52_2F2R)
     200        return 4;
     201    else
     202        return 2;
     203}
     204
     205void float2s16_multi (float * _f, int16_t * s16, int flags)
     206{
     207    int i;
     208    int32_t * f = (int32_t *) _f;
     209
     210    switch (flags) {
     211    case A52_MONO:
     212        for (i = 0; i < 256; i++) {
     213            s16[5*i] = s16[5*i+1] = s16[5*i+2] = s16[5*i+3] = 0;
     214            s16[5*i+4] = convert (f[i]);
     215        }
     216        break;
     217    case A52_CHANNEL:
     218    case A52_STEREO:
     219    case A52_DOLBY:
     220        float2s16_2 (_f, s16);
     221        break;
     222    case A52_3F:
     223        for (i = 0; i < 256; i++) {
     224            s16[5*i] = convert (f[i]);
     225            s16[5*i+1] = convert (f[i+512]);
     226            s16[5*i+2] = s16[5*i+3] = 0;
     227            s16[5*i+4] = convert (f[i+256]);
     228        }
     229        break;
     230    case A52_2F2R:
     231        float2s16_4 (_f, s16);
     232        break;
     233    case A52_3F2R:
     234        float2s16_5 (_f, s16);
     235        break;
     236    case A52_MONO | A52_LFE:
     237        for (i = 0; i < 256; i++) {
     238            s16[6*i] = s16[6*i+1] = s16[6*i+2] = s16[6*i+3] = 0;
     239            s16[6*i+4] = convert (f[i+256]);
     240            s16[6*i+5] = convert (f[i]);
     241        }
     242        break;
     243    case A52_CHANNEL | A52_LFE:
     244    case A52_STEREO | A52_LFE:
     245    case A52_DOLBY | A52_LFE:
     246        for (i = 0; i < 256; i++) {
     247            s16[6*i] = convert (f[i+256]);
     248            s16[6*i+1] = convert (f[i+512]);
     249            s16[6*i+2] = s16[6*i+3] = s16[6*i+4] = 0;
     250            s16[6*i+5] = convert (f[i]);
     251        }
     252        break;
     253    case A52_3F | A52_LFE:
     254        for (i = 0; i < 256; i++) {
     255            s16[6*i] = convert (f[i+256]);
     256            s16[6*i+1] = convert (f[i+768]);
     257            s16[6*i+2] = s16[6*i+3] = 0;
     258            s16[6*i+4] = convert (f[i+512]);
     259            s16[6*i+5] = convert (f[i]);
     260        }
     261        break;
     262    case A52_2F2R | A52_LFE:
     263        for (i = 0; i < 256; i++) {
     264            s16[6*i] = convert (f[i+256]);
     265            s16[6*i+1] = convert (f[i+512]);
     266            s16[6*i+2] = convert (f[i+768]);
     267            s16[6*i+3] = convert (f[i+1024]);
     268            s16[6*i+4] = 0;
     269            s16[6*i+5] = convert (f[i]);
     270        }
     271        break;
     272    case A52_3F2R | A52_LFE:
     273        for (i = 0; i < 256; i++) {
     274            s16[6*i] = convert (f[i+256]);
     275            s16[6*i+1] = convert (f[i+768]);
     276            s16[6*i+2] = convert (f[i+1024]);
     277            s16[6*i+3] = convert (f[i+1280]);
     278            s16[6*i+4] = convert (f[i+512]);
     279            s16[6*i+5] = convert (f[i]);
     280        }
     281        break;
     282    }
     283}
     284
     285
    145286/**** end */
    146287
    147288#define HEADER_SIZE 7
     
    183324                    /* update codec info */
    184325                    avctx->sample_rate = sample_rate;
    185326                    s->channels = ac3_channels[s->flags & 7];
     327                    if (avctx->cqp >= 0)
     328                        avctx->channels = avctx->cqp;
    186329                    if (s->flags & A52_LFE)
    187330                        s->channels++;
    188331                    if (avctx->channels == 0)
     
    205348            s->inbuf_ptr += len;
    206349            buf_size -= len;
    207350        } else {
     351            int chans;
    208352            flags = s->flags;
    209353            if (avctx->channels == 1)
    210354                flags = A52_MONO;
    211             else if (avctx->channels == 2)
    212                 flags = A52_STEREO;
     355            else if (avctx->channels == 2) {
     356                if (s->channels>2)
     357                    flags = A52_DOLBY;
     358                else
     359                    flags = A52_STEREO;
     360            }
    213361            else
    214362                flags |= A52_ADJUST_LEVEL;
    215363            level = 1;
     364            chans = channels_multi(flags);
    216365            if (s->a52_frame(s->state, s->inbuf, &flags, &level, 384)) {
    217366            fail:
    218367                s->inbuf_ptr = s->inbuf;
     
    222371            for (i = 0; i < 6; i++) {
    223372                if (s->a52_block(s->state))
    224373                    goto fail;
    225                 float_to_int(s->samples, out_samples + i * 256 * avctx->channels, avctx->channels);
     374                //float_to_int(s->samples, out_samples + i * 256 * avctx->channels, avctx->channels);
     375                float2s16_multi(s->samples, out_samples + i * 256 * chans, flags);
    226376            }
    227377            s->inbuf_ptr = s->inbuf;
    228378            s->frame_size = 0;
    229             *data_size = 6 * avctx->channels * 256 * sizeof(int16_t);
     379            //*data_size = 6 * avctx->channels * 256 * sizeof(int16_t);
     380            *data_size = 6 * chans * 256 * sizeof(int16_t);
    230381            break;
    231382        }
    232383    }
  • libs/libavcodec/ac3enc.c

     
    13621362{
    13631363    AC3EncodeContext *s = avctx->priv_data;
    13641364    int16_t *samples = data;
     1365    // expects L C R LS RS LFE
     1366    // audio format is L R LS RS C LFE
     1367    static int channel_index[6] = { 0, 4, 1, 2, 3, 5 };
     1368    /*
     1369     * A52->Analog->AC3Enc
     1370     * 1->0->0
     1371     * 3->1->2
     1372     * 4->2->3
     1373     * 5->3->4
     1374     * 2->4->1
     1375     * 0->5->5
     1376     */
    13651377    int i, j, k, v, ch;
    13661378    int16_t input_samples[N];
    13671379    int32_t mdct_coef[NB_BLOCKS][AC3_MAX_CHANNELS][N/2];
     
    13821394            /* compute input samples */
    13831395            memcpy(input_samples, s->last_samples[ch], N/2 * sizeof(int16_t));
    13841396            sinc = s->nb_all_channels;
    1385             sptr = samples + (sinc * (N/2) * i) + ch;
     1397            sptr = samples + (sinc * (N/2) * i) + channel_index[ch];
    13861398            for(j=0;j<N/2;j++) {
    13871399                v = *sptr;
    13881400                input_samples[j + N/2] = v;
     
    14031415            v = 14 - log2_tab(input_samples, N);
    14041416            if (v < 0)
    14051417                v = 0;
    1406             exp_samples[i][ch] = v - 8;
     1418            exp_samples[i][ch] = v - 9;
    14071419            lshift_tab(input_samples, N, v);
    14081420
    14091421            /* do the MDCT */