Recherche avancée

Médias (91)

Autres articles (104)

  • Support de tous types de médias

    10 avril 2011

    Contrairement à beaucoup de logiciels et autres plate-formes modernes de partage de documents, MediaSPIP a l’ambition de gérer un maximum de formats de documents différents qu’ils soient de type : images (png, gif, jpg, bmp et autres...) ; audio (MP3, Ogg, Wav et autres...) ; vidéo (Avi, MP4, Ogv, mpg, mov, wmv et autres...) ; contenu textuel, code ou autres (open office, microsoft office (tableur, présentation), web (html, css), LaTeX, Google Earth) (...)

  • Creating farms of unique websites

    13 avril 2011, par

    MediaSPIP platforms can be installed as a farm, with a single "core" hosted on a dedicated server and used by multiple websites.
    This allows (among other things) : implementation costs to be shared between several different projects / individuals rapid deployment of multiple unique sites creation of groups of like-minded sites, making it possible to browse media in a more controlled and selective environment than the major "open" (...)

  • Supporting all media types

    13 avril 2011, par

    Unlike most software and media-sharing platforms, MediaSPIP aims to manage as many different media types as possible. The following are just a few examples from an ever-expanding list of supported formats : images : png, gif, jpg, bmp and more audio : MP3, Ogg, Wav and more video : AVI, MP4, OGV, mpg, mov, wmv and more text, code and other data : OpenOffice, Microsoft Office (Word, PowerPoint, Excel), web (html, CSS), LaTeX, Google Earth and (...)

Sur d’autres sites (11077)

  • Using ffserver to stream older IP cam MJPEG to RTSP

    26 mai 2016, par tmar89

    I have an older Sony IP camera that has an MJPEG stream. I need to connect this to an NVR that only takes ONVIP or RTSP and I’m trying to use ffserver and ffmpeg to convert the MJPEG stream to RTSP but it’s not working. Any have some idea of what I may be doing wrong ? Saw an error in the attempted playback about an unsupported Protocol.
    Here is my ffserver config :

    Port 8090
    RTSPPort 5544
    BindAddress 0.0.0.0
    RTSPBindAddress 0.0.0.0
    MaxClients 100
    MaxBandwidth 10000

    <feed>
    File /tmp/feed27.ffm
    FileMaxSize 5M
    ACL allow 127.0.0.1
    </feed>

    <stream>
    Format rtp
    Feed feed27.ffm
    NoAudio
    VideoCodec mjpeg
    VideoFrameRate 30
    VideoSize 736x480
    </stream>

    And here is the ffmpeg command I am using :

    [tm@tele ffserver-rtsp]# ffmpeg -f mjpeg -r 30 -s 736x480 -i http://[CAMIP]/image http://localhost:8090/feed27.ffm
       FFmpeg version 0.6.5, Copyright (c) 2000-2010 the FFmpeg developers
         built on Jan 29 2012 17:52:15 with gcc 4.4.5 20110214 (Red Hat 4.4.5-6)
         configuration: --prefix=/usr --libdir=/usr/lib64 --shlibdir=/usr/lib64 --mandir=/usr/share/man --incdir=/usr/include --disable-avisynth --extra-cflags='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -fPIC' --enable-avfilter --enable-avfilter-lavf --enable-libdc1394 --enable-libdirac --enable-libfaac --enable-libfaad --enable-libfaadbin --enable-libgsm --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-librtmp --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libx264 --enable-gpl --enable-nonfree --enable-postproc --enable-pthreads --enable-shared --enable-swscale --enable-vdpau --enable-version3 --enable-x11grab
         libavutil     50.15. 1 / 50.15. 1
         libavcodec    52.72. 2 / 52.72. 2
         libavformat   52.64. 2 / 52.64. 2
         libavdevice   52. 2. 0 / 52. 2. 0
         libavfilter    1.19. 0 /  1.19. 0
         libswscale     0.11. 0 /  0.11. 0
         libpostproc   51. 2. 0 / 51. 2. 0
       [mjpeg @ 0x1ece670]Estimating duration from bitrate, this may be inaccurate
       Input #0, mjpeg, from 'http://[CAMIP]/image':
         Duration: N/A, bitrate: N/A
           Stream #0.0: Video: mjpeg, yuvj422p, 736x480, 30 fps, 30 tbr, 1200k tbn, 30 tbc
       Output #0, ffm, to 'http://localhost:8090/feed27.ffm':
         Metadata:
           encoder         : Lavf52.64.2
           Stream #0.0: Video: mjpeg, yuvj420p, 736x480, q=2-31, 200 kb/s, 1000k tbn, 30 tbc
       Stream mapping:
         Stream #0.0 -> #0.0
       Press [q] to stop encoding
       [mjpeg @ 0x222d110]rc buffer underflow
       frame=  640 fps= 17 q=31.4 size=   12884kB time=21.33 bitrate=4947.5kbits/s

    When I use VLC to open the stream, it cannot be found :

    Your input can't be opened:
       VLC is unable to open the MRL 'rtsp://localhost:5544/stream27.mpg'. Check the log for details.

    Finally, using ffplay on the same machine :

    [tm@tele tmp]# ffplay rtsp://localhost:5544/stream27.sdp
    FFplay version 0.6.5, Copyright (c) 2003-2010 the FFmpeg developers
     built on Jan 29 2012 17:52:15 with gcc 4.4.5 20110214 (Red Hat 4.4.5-6)
     configuration: --prefix=/usr --libdir=/usr/lib64 --shlibdir=/usr/lib64 --mandir=/usr/share/man --incdir=/usr/include --disable-avisynth --extra-cflags='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -fPIC' --enable-avfilter --enable-avfilter-lavf --enable-libdc1394 --enable-libdirac --enable-libfaac --enable-libfaad --enable-libfaadbin --enable-libgsm --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-librtmp --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libx264 --enable-gpl --enable-nonfree --enable-postproc --enable-pthreads --enable-shared --enable-swscale --enable-vdpau --enable-version3 --enable-x11grab
     libavutil     50.15. 1 / 50.15. 1
     libavcodec    52.72. 2 / 52.72. 2
     libavformat   52.64. 2 / 52.64. 2
     libavdevice   52. 2. 0 / 52. 2. 0
     libavfilter    1.19. 0 /  1.19. 0
     libswscale     0.11. 0 /  0.11. 0
     libpostproc   51. 2. 0 / 51. 2. 0
    ALSA lib pulse.c:229:(pulse_connect) PulseAudio: Unable to connect: Connection refused

    rtsp://localhost:5544/stream27.sdp: Protocol not supported

    And here was the log from ffserver :

    127.0.0.1:5000 - - "PLAY stream27.mpg/streamid=0 RTP/UDP"
    [rtp @ 0x721dc0]Unsupported codec 8
    127.0.0.1:0 - - "PLAY stream27.mpg/streamid=0 RTP/TCP"
    [rtp @ 0x728cb0]Unsupported codec 8
    127.0.0.1 - - [SETUP] "rtsp://localhost:5544/stream27.mpg/streamid=0 RTSP/1.0" 200 641
  • How to stop ffmpeg when there's no incoming rtmp stream

    5 juillet 2016, par M. Irich

    I use ffmpeg together with nginx-rtmp.
    The thing is ffmpeg doesn’t finish the process when the stream’s finished

    I use the following command :

    ffmpeg  -i 'rtmp://localhost:443/live/test' -loglevel debug  -c:a libfdk_aac -b:a 192k -c:v libx264 -profile baseline -preset superfast -tune zerolatency -b:v 2500k -maxrate 4500k -minrate 1500k -bufsize 9000k -keyint_min 15 -g 15 -f dash -use_timeline 1 -use_template 1 -min_seg_duration 5000 -y /tmp/dash/test/test.mpd

    but even the stream’s not running ffmpeg still can’t finish the process and is waiting for the rtmp stream

    Successfully parsed a group of options.
    Opening an input file: rtmp://localhost:443/live/test.
    [rtmp @ 0x2ba2160] No default whitelist set
    [tcp @ 0x2ba2720] No default whitelist set
    [rtmp @ 0x2ba2160] Handshaking...
    [rtmp @ 0x2ba2160] Type answer 3
    [rtmp @ 0x2ba2160] Server version 13.14.10.13
    [rtmp @ 0x2ba2160] Proto = rtmp, path = /live/test, app = live, fname = test
    [rtmp @ 0x2ba2160] Server bandwidth = 5000000
    [rtmp @ 0x2ba2160] Client bandwidth = 5000000
    [rtmp @ 0x2ba2160] New incoming chunk size = 4096
    [rtmp @ 0x2ba2160] Creating stream...
    [rtmp @ 0x2ba2160] Sending play command for 'test'

    Is it possible to limit the latency time to several seconds ?

    Sorry for any possible mistakes - English’s not my native language.

  • Decoding and playing audio with ffmpeg and XAudio2 - frequency ratio wrong

    9 mars, par Brent de Carteret

    I'm using ffmpeg to decode audio and output it using the XAudio2 API, it works and plays synced with the video output using the pts. But it's high pitched (i.e. sounds like chipmunks).

    &#xA;

    Setting breakpoints I can see it has set the correct sample rate from the audio codec in CreateSourceVoice. I'm stumped.

    &#xA;

    Any help would be much appreciated.

    &#xA;

    CDVDAUDIO.cpp

    &#xA;

    #include "DVDAudioDevice.h"&#xA;   &#xA;HANDLE m_hBufferEndEvent;&#xA;&#xA;CDVDAudio::CDVDAudio()&#xA;{&#xA;    m_pXAudio2 = NULL;&#xA;    m_pMasteringVoice = NULL;&#xA;    m_pSourceVoice = NULL;&#xA;    m_pWfx  = NULL;&#xA;    m_VoiceCallback = NULL;    &#xA;    m_hBufferEndEvent = CreateEvent(NULL, false, false, "Buffer end event");&#xA;}&#xA;    &#xA;CDVDAudio::~CDVDAudio()&#xA;{&#xA;    m_pXAudio2 = NULL;&#xA;    m_pMasteringVoice = NULL;&#xA;    m_pSourceVoice = NULL;&#xA;    m_pWfx  = NULL;&#xA;    m_VoiceCallback = NULL;&#xA;    CloseHandle(m_hBufferEndEvent);&#xA;    m_hBufferEndEvent = NULL;&#xA;}&#xA;    &#xA;bool CDVDAudio::Create(int iChannels, int iBitrate, int iBitsPerSample, bool bPasstrough)&#xA;{&#xA;    CoInitializeEx(NULL, COINIT_MULTITHREADED);&#xA;    HRESULT hr = XAudio2Create( &amp;m_pXAudio2, 0, XAUDIO2_DEFAULT_PROCESSOR);&#xA;    &#xA;    if (SUCCEEDED(hr))&#xA;    {&#xA;        m_pXAudio2->CreateMasteringVoice( &amp;m_pMasteringVoice );&#xA;    }&#xA;    &#xA;    // Create source voice&#xA;    WAVEFORMATEXTENSIBLE wfx;&#xA;    memset(&amp;wfx, 0, sizeof(WAVEFORMATEXTENSIBLE));&#xA;    &#xA;    wfx.Format.wFormatTag           = WAVE_FORMAT_PCM;&#xA;    wfx.Format.nSamplesPerSec       = iBitrate;//pFFMpegData->pAudioCodecCtx->sample_rate;//48000 by default&#xA;    wfx.Format.nChannels            = iChannels;//pFFMpegData->pAudioCodecCtx->channels;&#xA;    wfx.Format.wBitsPerSample       = 16;&#xA;    wfx.Format.nBlockAlign          = wfx.Format.nChannels*16/8;&#xA;    wfx.Format.nAvgBytesPerSec      = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign;&#xA;    wfx.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);&#xA;    wfx.Samples.wValidBitsPerSample = wfx.Format.wBitsPerSample;&#xA;    &#xA;    if(wfx.Format.nChannels == 1)&#xA;    {&#xA;        wfx.dwChannelMask = SPEAKER_MONO;&#xA;    }&#xA;    else if(wfx.Format.nChannels == 2)&#xA;    {&#xA;        wfx.dwChannelMask = SPEAKER_STEREO;&#xA;    }&#xA;    else if(wfx.Format.nChannels == 5)&#xA;    {&#xA;        wfx.dwChannelMask = SPEAKER_5POINT1;&#xA;    }&#xA;    &#xA;    wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;&#xA;    &#xA;    unsigned int flags = 0;//XAUDIO2_VOICE_NOSRC;// | XAUDIO2_VOICE_NOPITCH;&#xA;        &#xA;    //Source voice&#xA;    m_VoiceCallback = new StreamingVoiceCallback(this);&#xA;    hr = m_pXAudio2->CreateSourceVoice(&amp;m_pSourceVoice,(WAVEFORMATEX*)&amp;wfx, 0 , 1.0f, m_VoiceCallback);&#xA;        &#xA;    if (!SUCCEEDED(hr))&#xA;        return false;&#xA;    &#xA;    // Start sound&#xA;    hr = m_pSourceVoice->Start(0);&#xA;    &#xA;    if(!SUCCEEDED(hr))&#xA;        return false;&#xA;    &#xA;    return true;&#xA;}&#xA;    &#xA;DWORD CDVDAudio::AddPackets(unsigned char* data, DWORD len)&#xA;{  &#xA;    memset(&amp;m_SoundBuffer,0,sizeof(XAUDIO2_BUFFER));&#xA;    m_SoundBuffer.AudioBytes = len;&#xA;    m_SoundBuffer.pAudioData = data;&#xA;    m_SoundBuffer.pContext = NULL;//(VOID*)data;&#xA;    XAUDIO2_VOICE_STATE state;&#xA;    &#xA;    while (m_pSourceVoice->GetState( &amp;state ), state.BuffersQueued > 60)&#xA;    {&#xA;        WaitForSingleObject( m_hBufferEndEvent, INFINITE );&#xA;    }&#xA;    &#xA;    m_pSourceVoice->SubmitSourceBuffer( &amp;m_SoundBuffer );&#xA;    return 0;&#xA;}&#xA;    &#xA;void CDVDAudio::Destroy()&#xA;{&#xA;    m_pMasteringVoice->DestroyVoice();&#xA;    m_pXAudio2->Release();&#xA;    m_pSourceVoice->DestroyVoice();&#xA;    delete m_VoiceCallback;&#xA;    m_VoiceCallback = NULL;&#xA;}&#xA;

    &#xA;

    CDVDAUdioCodecFFmpeg.cpp

    &#xA;

    #include "DVDAudioCodecFFmpeg.h"&#xA;#include "Log.h"&#xA;    &#xA;CDVDAudioCodecFFmpeg::CDVDAudioCodecFFmpeg() : CDVDAudioCodec()&#xA;{&#xA;    m_iBufferSize = 0;&#xA;    m_pCodecContext = NULL;&#xA;    m_bOpenedCodec = false;&#xA;}&#xA;    &#xA;CDVDAudioCodecFFmpeg::~CDVDAudioCodecFFmpeg()&#xA;{&#xA;    Dispose();&#xA;}&#xA;    &#xA;bool CDVDAudioCodecFFmpeg::Open(AVCodecID codecID, int iChannels, int iSampleRate)&#xA;{&#xA;    AVCodec* pCodec;&#xA;    m_bOpenedCodec = false;&#xA;    av_register_all();&#xA;    pCodec = avcodec_find_decoder(codecID);&#xA;    m_pCodecContext = avcodec_alloc_context3(pCodec);//avcodec_alloc_context();&#xA;    avcodec_get_context_defaults3(m_pCodecContext, pCodec);&#xA;    &#xA;    if (!pCodec)&#xA;    {&#xA;        CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::Open() Unable to find codec");&#xA;        return false;&#xA;    }&#xA;    &#xA;    m_pCodecContext->debug_mv = 0;&#xA;    m_pCodecContext->debug = 0;&#xA;    m_pCodecContext->workaround_bugs = 1;&#xA;    &#xA;    if (pCodec->capabilities &amp; CODEC_CAP_TRUNCATED)&#xA;        m_pCodecContext->flags |= CODEC_FLAG_TRUNCATED;&#xA;    &#xA;    m_pCodecContext->channels = iChannels;&#xA;    m_pCodecContext->sample_rate = iSampleRate;&#xA;    //m_pCodecContext->bits_per_sample = 24;&#xA;     &#xA;    /* //FIXME BRENT&#xA;        if( ExtraData &amp;&amp; ExtraSize > 0 )&#xA;        {&#xA;            m_pCodecContext->extradata_size = ExtraSize;&#xA;            m_pCodecContext->extradata = m_dllAvCodec.av_mallocz(ExtraSize &#x2B; FF_INPUT_BUFFER_PADDING_SIZE);&#xA;            memcpy(m_pCodecContext->extradata, ExtraData, ExtraSize);&#xA;        }&#xA;    */&#xA;    &#xA;    // set acceleration&#xA;    //m_pCodecContext->dsp_mask = FF_MM_FORCE | FF_MM_MMX | FF_MM_MMXEXT | FF_MM_SSE; //BRENT&#xA;    &#xA;    if (avcodec_open2(m_pCodecContext, pCodec, NULL) &lt; 0)&#xA;    {&#xA;        CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::Open() Unable to open codec");&#xA;        Dispose();&#xA;        return false;&#xA;    }&#xA;    &#xA;    m_bOpenedCodec = true;&#xA;    return true;&#xA;}&#xA;    &#xA;void CDVDAudioCodecFFmpeg::Dispose()&#xA;{&#xA;    if (m_pCodecContext)&#xA;    {&#xA;        if (m_bOpenedCodec)&#xA;            avcodec_close(m_pCodecContext);&#xA;        m_bOpenedCodec = false;&#xA;        av_free(m_pCodecContext);&#xA;        m_pCodecContext = NULL;&#xA;    }&#xA;    m_iBufferSize = 0;&#xA;}&#xA;&#xA;int CDVDAudioCodecFFmpeg::Decode(BYTE* pData, int iSize)&#xA;{&#xA;    int iBytesUsed;&#xA;    if (!m_pCodecContext) return -1;&#xA;    &#xA;    //Copy into a FFMpeg AVPAcket again&#xA;    AVPacket packet;&#xA;    av_init_packet(&amp;packet);&#xA;    &#xA;    packet.data=pData;&#xA;    packet.size=iSize;&#xA;    &#xA;    int iOutputSize = AVCODEC_MAX_AUDIO_FRAME_SIZE; //BRENT&#xA;    &#xA;    iBytesUsed = avcodec_decode_audio3(m_pCodecContext, (int16_t *)m_buffer, &amp;iOutputSize/*m_iBufferSize*/, &amp;packet);&#xA;&#xA;    m_iBufferSize = iOutputSize;//BRENT&#xA;&#xA;    return iBytesUsed;&#xA;}&#xA;&#xA;int CDVDAudioCodecFFmpeg::GetData(BYTE** dst)&#xA;{&#xA;    *dst = m_buffer;&#xA;    return m_iBufferSize;&#xA;}&#xA;&#xA;void CDVDAudioCodecFFmpeg::Reset()&#xA;{&#xA;    if (m_pCodecContext)&#xA;        avcodec_flush_buffers(m_pCodecContext);&#xA;}&#xA;&#xA;int CDVDAudioCodecFFmpeg::GetChannels()&#xA;{&#xA;    if (m_pCodecContext)&#xA;        return m_pCodecContext->channels;&#xA;    return 0;&#xA;}&#xA;&#xA;int CDVDAudioCodecFFmpeg::GetSampleRate()&#xA;{&#xA;    if (m_pCodecContext)&#xA;        return m_pCodecContext->sample_rate;&#xA;    return 0;&#xA;}&#xA;    &#xA;int CDVDAudioCodecFFmpeg::GetBitsPerSample()&#xA;{&#xA;    if (m_pCodecContext)&#xA;        return 16;&#xA;    return 0;&#xA;}&#xA;

    &#xA;

    CDVDPlayerAudio.cpp

    &#xA;

    #include "DVDPlayerAudio.h"&#xA;#include "DVDDemuxUtils.h"&#xA;#include "Log.h"&#xA;    &#xA;#include &#xA;#include "DVDAudioCodecFFmpeg.h" //FIXME Move to a codec factory!!&#xA;    &#xA;CDVDPlayerAudio::CDVDPlayerAudio(CDVDClock* pClock) : CThread()&#xA;{&#xA;    m_pClock = pClock;&#xA;    m_pAudioCodec = NULL;&#xA;    m_bInitializedOutputDevice = false;&#xA;    m_iSourceChannels = 0;&#xA;    m_audioClock = 0;&#xA;    &#xA;    //  m_currentPTSItem.pts = DVD_NOPTS_VALUE;&#xA;    //  m_currentPTSItem.timestamp = 0;&#xA;    &#xA;    SetSpeed(DVD_PLAYSPEED_NORMAL);&#xA;      &#xA;    InitializeCriticalSection(&amp;m_critCodecSection);&#xA;    m_messageQueue.SetMaxDataSize(10 * 16 * 1024);&#xA;    //  g_dvdPerformanceCounter.EnableAudioQueue(&amp;m_packetQueue);&#xA;}&#xA;&#xA;CDVDPlayerAudio::~CDVDPlayerAudio()&#xA;{&#xA;    //  g_dvdPerformanceCounter.DisableAudioQueue();&#xA;&#xA;    // close the stream, and don&#x27;t wait for the audio to be finished&#xA;    CloseStream(true);&#xA;    DeleteCriticalSection(&amp;m_critCodecSection);&#xA;}&#xA;&#xA;bool CDVDPlayerAudio::OpenStream( CDemuxStreamAudio *pDemuxStream )&#xA;{&#xA;    // should always be NULL!!!!, it will probably crash anyway when deleting m_pAudioCodec here.&#xA;    if (m_pAudioCodec)&#xA;    {&#xA;        CLog::Log(LOGFATAL, "CDVDPlayerAudio::OpenStream() m_pAudioCodec != NULL");&#xA;        return false;&#xA;    }&#xA;    &#xA;    AVCodecID codecID = pDemuxStream->codec;&#xA;    &#xA;    CLog::Log(LOGNOTICE, "Finding audio codec for: %i", codecID);&#xA;    //m_pAudioCodec = CDVDFactoryCodec::CreateAudioCodec( pDemuxStream ); &#xA;    m_pAudioCodec = new CDVDAudioCodecFFmpeg; //FIXME BRENT Codec Factory needed!&#xA;    &#xA;    if (!m_pAudioCodec->Open(pDemuxStream->codec, pDemuxStream->iChannels, pDemuxStream->iSampleRate))&#xA;    {&#xA;        m_pAudioCodec->Dispose();&#xA;        delete m_pAudioCodec;&#xA;        m_pAudioCodec = NULL;&#xA;        return false;&#xA;    }&#xA;    &#xA;    if ( !m_pAudioCodec )&#xA;    {&#xA;        CLog::Log(LOGERROR, "Unsupported audio codec");&#xA;        return false;&#xA;    }&#xA;    &#xA;    m_codec = pDemuxStream->codec;&#xA;    m_iSourceChannels = pDemuxStream->iChannels;&#xA;    m_messageQueue.Init();&#xA;    &#xA;    CLog::Log(LOGNOTICE, "Creating audio thread");&#xA;    Create();&#xA;    &#xA;    return true;&#xA;}&#xA;&#xA;void CDVDPlayerAudio::CloseStream(bool bWaitForBuffers)&#xA;{&#xA;    // wait until buffers are empty&#xA;    if (bWaitForBuffers)&#xA;        m_messageQueue.WaitUntilEmpty();&#xA;    &#xA;    // send abort message to the audio queue&#xA;    m_messageQueue.Abort();&#xA;    &#xA;    CLog::Log(LOGNOTICE, "waiting for audio thread to exit");&#xA;    &#xA;    // shut down the audio_decode thread and wait for it&#xA;    StopThread(); // will set this->m_bStop to true&#xA;    this->WaitForThreadExit(INFINITE);&#xA;    &#xA;    // uninit queue&#xA;    m_messageQueue.End();&#xA;    &#xA;    CLog::Log(LOGNOTICE, "Deleting audio codec");&#xA;    if (m_pAudioCodec)&#xA;    {&#xA;        m_pAudioCodec->Dispose();&#xA;        delete m_pAudioCodec;&#xA;        m_pAudioCodec = NULL;&#xA;    }&#xA;    &#xA;    // flush any remaining pts values&#xA;    //FlushPTSQueue(); //FIXME BRENT&#xA;}&#xA;&#xA;void CDVDPlayerAudio::OnStartup()&#xA;{&#xA;    CThread::SetName("CDVDPlayerAudio");&#xA;    pAudioPacket = NULL;&#xA;    m_audioClock = 0;&#xA;    audio_pkt_data = NULL;&#xA;    audio_pkt_size = 0;&#xA;  &#xA;    //  g_dvdPerformanceCounter.EnableAudioDecodePerformance(ThreadHandle());&#xA;}&#xA;&#xA;void CDVDPlayerAudio::Process()&#xA;{&#xA;    CLog::Log(LOGNOTICE, "running thread: CDVDPlayerAudio::Process()");&#xA;&#xA;    int result;&#xA;    &#xA;    // silence data&#xA;    BYTE silence[1024];&#xA;    memset(silence, 0, 1024);&#xA;    &#xA;    DVDAudioFrame audioframe;&#xA;    &#xA;    __int64 iClockDiff=0;&#xA;    while (!m_bStop)&#xA;    {&#xA;        //Don&#x27;t let anybody mess with our global variables&#xA;        EnterCriticalSection(&amp;m_critCodecSection);&#xA;        result = DecodeFrame(audioframe, m_speed != DVD_PLAYSPEED_NORMAL); // blocks if no audio is available, but leaves critical section before doing so&#xA;        LeaveCriticalSection(&amp;m_critCodecSection);&#xA;    &#xA;        if ( result &amp; DECODE_FLAG_ERROR ) &#xA;        {      &#xA;            CLog::Log(LOGERROR, "CDVDPlayerAudio::Process - Decode Error. Skipping audio frame");&#xA;            continue;&#xA;        }&#xA;    &#xA;        if ( result &amp; DECODE_FLAG_ABORT )&#xA;        {&#xA;            CLog::Log(LOGDEBUG, "CDVDPlayerAudio::Process - Abort received, exiting thread");&#xA;            break;&#xA;        }&#xA;    &#xA;        if ( result &amp; DECODE_FLAG_DROP ) //FIXME BRENT&#xA;        {&#xA;            /*  //frame should be dropped. Don&#x27;t let audio move ahead of the current time thou&#xA;                //we need to be able to start playing at any time&#xA;                //when playing backwards, we try to keep as small buffers as possible&#xA;    &#xA;                // set the time at this delay&#xA;                AddPTSQueue(audioframe.pts, m_dvdAudio.GetDelay());&#xA;            */&#xA;            if (m_speed > 0)&#xA;            {&#xA;                __int64 timestamp = m_pClock->GetAbsoluteClock() &#x2B; (audioframe.duration * DVD_PLAYSPEED_NORMAL) / m_speed;&#xA;                while ( !m_bStop &amp;&amp; timestamp > m_pClock->GetAbsoluteClock() )&#xA;                    Sleep(1);&#xA;            }&#xA;            continue;&#xA;        }&#xA;    &#xA;        if ( audioframe.size > 0 ) &#xA;        {&#xA;            // we have successfully decoded an audio frame, open up the audio device if not already done&#xA;            if (!m_bInitializedOutputDevice)&#xA;            {&#xA;                m_bInitializedOutputDevice = InitializeOutputDevice();&#xA;            }&#xA;    &#xA;            //Add any packets play&#xA;            m_dvdAudio.AddPackets(audioframe.data, audioframe.size);&#xA;    &#xA;            // store the delay for this pts value so we can calculate the current playing&#xA;            //AddPTSQueue(audioframe.pts, m_dvdAudio.GetDelay() - audioframe.duration);//BRENT&#xA;        }&#xA;    &#xA;        // if we where asked to resync on this packet, do so here&#xA;        if ( result &amp; DECODE_FLAG_RESYNC )&#xA;        {&#xA;            CLog::Log(LOGDEBUG, "CDVDPlayerAudio::Process - Resync recieved.");&#xA;            //while (!m_bStop &amp;&amp; (unsigned int)m_dvdAudio.GetDelay() > audioframe.duration ) Sleep(5); //BRENT&#xA;            m_pClock->Discontinuity(CLOCK_DISC_NORMAL, audioframe.pts);&#xA;        }&#xA;    &#xA;        #ifdef USEOLDSYNC&#xA;        //Clock should be calculated after packets have been added as m_audioClock points to the &#xA;        //time after they have been played&#xA;    &#xA;        const __int64 iCurrDiff = (m_audioClock - m_dvdAudio.GetDelay()) - m_pClock->GetClock();&#xA;        const __int64 iAvDiff = (iClockDiff &#x2B; iCurrDiff)/2;&#xA;    &#xA;        //Check for discontinuity in the stream, use a moving average to&#xA;        //eliminate highfreq fluctuations of large packet sizes&#xA;        if ( ABS(iAvDiff) > 5000 ) // sync clock if average diff is bigger than 5 msec &#xA;        {&#xA;            //Wait until only the new audio frame which triggered the discontinuity is left&#xA;            //then set disc state&#xA;            while (!m_bStop &amp;&amp; (unsigned int)m_dvdAudio.GetBytesInBuffer() > audioframe.size )&#xA;                Sleep(5);&#xA;    &#xA;            m_pClock->Discontinuity(CLOCK_DISC_NORMAL, m_audioClock - m_dvdAudio.GetDelay());&#xA;            CLog::("CDVDPlayer:: Detected Audio Discontinuity, syncing clock. diff was: %I64d, %I64d, av: %I64d", iClockDiff, iCurrDiff, iAvDiff);&#xA;            iClockDiff = 0;&#xA;        }&#xA;        else&#xA;        {&#xA;            //Do gradual adjustments (not working yet)&#xA;            //m_pClock->AdjustSpeedToMatch(iClock &#x2B; iAvDiff);&#xA;            iClockDiff = iCurrDiff;&#xA;        }&#xA;        #endif&#xA;    }&#xA;}&#xA;&#xA;void CDVDPlayerAudio::OnExit()&#xA;{&#xA;    //g_dvdPerformanceCounter.DisableAudioDecodePerformance();&#xA;  &#xA;    // destroy audio device&#xA;    CLog::Log(LOGNOTICE, "Closing audio device");&#xA;    m_dvdAudio.Destroy();&#xA;    m_bInitializedOutputDevice = false;&#xA;&#xA;    CLog::Log(LOGNOTICE, "thread end: CDVDPlayerAudio::OnExit()");&#xA;}&#xA;&#xA;// decode one audio frame and returns its uncompressed size&#xA;int CDVDPlayerAudio::DecodeFrame(DVDAudioFrame &amp;audioframe, bool bDropPacket)&#xA;{&#xA;    CDVDDemux::DemuxPacket* pPacket = pAudioPacket;&#xA;    int n=48000*2*16/8, len;&#xA;    &#xA;    //Store amount left at this point, and what last pts was&#xA;    unsigned __int64 first_pkt_pts = 0;&#xA;    int first_pkt_size = 0; &#xA;    int first_pkt_used = 0;&#xA;    int result = 0;&#xA;    &#xA;    // make sure the sent frame is clean&#xA;    memset(&amp;audioframe, 0, sizeof(DVDAudioFrame));&#xA;    &#xA;    if (pPacket)&#xA;    {&#xA;        first_pkt_pts = pPacket->pts;&#xA;        first_pkt_size = pPacket->iSize;&#xA;        first_pkt_used = first_pkt_size - audio_pkt_size;&#xA;    }&#xA;     &#xA;    for (;;)&#xA;    {&#xA;        /* NOTE: the audio packet can contain several frames */&#xA;        while (audio_pkt_size > 0)&#xA;        {&#xA;            len = m_pAudioCodec->Decode(audio_pkt_data, audio_pkt_size);&#xA;            if (len &lt; 0)&#xA;            {&#xA;                /* if error, we skip the frame */&#xA;                audio_pkt_size=0;&#xA;                m_pAudioCodec->Reset();&#xA;                break;&#xA;            }&#xA;    &#xA;            // fix for fucked up decoders //FIXME BRENT&#xA;            if( len > audio_pkt_size )&#xA;            {        &#xA;                CLog::Log(LOGERROR, "CDVDPlayerAudio:DecodeFrame - Codec tried to consume more data than available. Potential memory corruption");        &#xA;                audio_pkt_size=0;&#xA;                m_pAudioCodec->Reset();&#xA;                assert(0);&#xA;            }&#xA;    &#xA;            // get decoded data and the size of it&#xA;            audioframe.size = m_pAudioCodec->GetData(&amp;audioframe.data);&#xA;            audio_pkt_data &#x2B;= len;&#xA;            audio_pkt_size -= len;&#xA;    &#xA;            if (audioframe.size &lt;= 0)&#xA;                continue;&#xA;    &#xA;            audioframe.pts = m_audioClock;&#xA;    &#xA;            // compute duration.&#xA;            n = m_pAudioCodec->GetChannels() * m_pAudioCodec->GetBitsPerSample() / 8 * m_pAudioCodec->GetSampleRate();&#xA;            if (n > 0)&#xA;            {&#xA;                // safety check, if channels == 0, n will result in 0, and that will result in a nice divide exception&#xA;                audioframe.duration = (unsigned int)(((__int64)audioframe.size * DVD_TIME_BASE) / n);&#xA;    &#xA;                // increase audioclock to after the packet&#xA;                m_audioClock &#x2B;= audioframe.duration;&#xA;            }&#xA;    &#xA;            //If we are asked to drop this packet, return a size of zero. then it won&#x27;t be played&#xA;            //we currently still decode the audio.. this is needed since we still need to know it&#x27;s &#xA;            //duration to make sure clock is updated correctly.&#xA;            if ( bDropPacket )&#xA;            {&#xA;                result |= DECODE_FLAG_DROP;&#xA;            }&#xA;            return result;&#xA;        }&#xA;    &#xA;        // free the current packet&#xA;        if (pPacket)&#xA;        {&#xA;            CDVDDemuxUtils::FreeDemuxPacket(pPacket); //BRENT FIXME&#xA;            pPacket = NULL;&#xA;            pAudioPacket = NULL;&#xA;        }&#xA;    &#xA;        if (m_messageQueue.RecievedAbortRequest())&#xA;            return DECODE_FLAG_ABORT;&#xA;    &#xA;        // read next packet and return -1 on error&#xA;        LeaveCriticalSection(&amp;m_critCodecSection); //Leave here as this might stall a while&#xA;    &#xA;        CDVDMsg* pMsg;&#xA;        MsgQueueReturnCode ret = m_messageQueue.Get(&amp;pMsg, INFINITE);&#xA;        EnterCriticalSection(&amp;m_critCodecSection);&#xA;            &#xA;        if (MSGQ_IS_ERROR(ret) || ret == MSGQ_ABORT)&#xA;            return DECODE_FLAG_ABORT;&#xA;    &#xA;        if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET))&#xA;        {&#xA;            CDVDMsgDemuxerPacket* pMsgDemuxerPacket = (CDVDMsgDemuxerPacket*)pMsg;&#xA;            pPacket = pMsgDemuxerPacket->GetPacket();&#xA;            pMsgDemuxerPacket->m_pPacket = NULL; // XXX, test&#xA;            pAudioPacket = pPacket;&#xA;            audio_pkt_data = pPacket->pData;&#xA;            audio_pkt_size = pPacket->iSize;&#xA;        }&#xA;        else&#xA;        {&#xA;            // other data is not used here, free if&#xA;            // msg itself will still be available&#xA;            pMsg->Release();&#xA;        }&#xA; &#xA;        // if update the audio clock with the pts&#xA;        if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET) || pMsg->IsType(CDVDMsg::GENERAL_RESYNC))&#xA;        {&#xA;            if (pMsg->IsType(CDVDMsg::GENERAL_RESYNC))&#xA;            { &#xA;                //player asked us to sync on this package&#xA;                CDVDMsgGeneralResync* pMsgGeneralResync = (CDVDMsgGeneralResync*)pMsg;&#xA;                result |= DECODE_FLAG_RESYNC;&#xA;                m_audioClock = pMsgGeneralResync->GetPts();&#xA;            }&#xA;            else if (pPacket->pts != DVD_NOPTS_VALUE) // CDVDMsg::DEMUXER_PACKET, pPacket is already set above&#xA;            {&#xA;                if (first_pkt_size == 0) &#xA;                { &#xA;                    //first package&#xA;                    m_audioClock = pPacket->pts;        &#xA;                }&#xA;                else if (first_pkt_pts > pPacket->pts)&#xA;                { &#xA;                    //okey first packet in this continous stream, make sure we use the time here        &#xA;                    m_audioClock = pPacket->pts;        &#xA;                }&#xA;                else if ((unsigned __int64)m_audioClock &lt; pPacket->pts || (unsigned __int64)m_audioClock > pPacket->pts)&#xA;                {&#xA;                    //crap, moved outsided correct pts&#xA;                    //Use pts from current packet, untill we find a better value for it.&#xA;                    //Should be ok after a couple of frames, as soon as it starts clean on a packet&#xA;                    m_audioClock = pPacket->pts;&#xA;                }&#xA;                else if (first_pkt_size == first_pkt_used)&#xA;                {&#xA;                    //Nice starting up freshly on the start of a packet, use pts from it&#xA;                    m_audioClock = pPacket->pts;&#xA;                }&#xA;            }&#xA;        }&#xA;        pMsg->Release();&#xA;    }&#xA;}&#xA;&#xA;void CDVDPlayerAudio::SetSpeed(int speed)&#xA;{ &#xA;    m_speed = speed;&#xA;  &#xA;    //if (m_speed == DVD_PLAYSPEED_PAUSE) m_dvdAudio.Pause(); //BRENT FIXME&#xA;    //else m_dvdAudio.Resume();&#xA;}&#xA;    &#xA;bool CDVDPlayerAudio::InitializeOutputDevice()&#xA;{&#xA;    int iChannels = m_pAudioCodec->GetChannels();&#xA;    int iSampleRate = m_pAudioCodec->GetSampleRate();&#xA;    int iBitsPerSample = m_pAudioCodec->GetBitsPerSample();&#xA;    //bool bPasstrough = m_pAudioCodec->NeedPasstrough(); //BRENT&#xA;    &#xA;    if (iChannels == 0 || iSampleRate == 0 || iBitsPerSample == 0)&#xA;    {&#xA;        CLog::Log(LOGERROR, "Unable to create audio device, (iChannels == 0 || iSampleRate == 0 || iBitsPerSample == 0)");&#xA;        return false;&#xA;    }&#xA;    &#xA;    CLog::Log(LOGNOTICE, "Creating audio device with codec id: %i, channels: %i, sample rate: %i", m_codec, iChannels, iSampleRate);&#xA;    if (m_dvdAudio.Create(iChannels, iSampleRate, iBitsPerSample, /*bPasstrough*/0)) // always 16 bit with ffmpeg ? //BRENT Passthrough needed?&#xA;    {&#xA;        return true;&#xA;    }&#xA;    &#xA;    CLog::Log(LOGERROR, "Failed Creating audio device with codec id: %i, channels: %i, sample rate: %i", m_codec, iChannels, iSampleRate);&#xA;    return false;&#xA;}&#xA;

    &#xA;