svvitch
digital signage player
|
00001 #ifdef USE_FFMPEG 00002 00003 #include <Poco/format.h> 00004 #include <Poco/Logger.h> 00005 #include <Poco/Mutex.h> 00006 #include <Poco/Thread.h> 00007 #include <Poco/UnicodeConverter.h> 00008 #include "FFAudioDecoder.h" 00009 #include "PerformanceTimer.h" 00010 00011 00012 FFAudioDecoder::FFAudioDecoder(Renderer& renderer, AVFormatContext* ic, const int streamNo): FFBaseDecoder(renderer, ic, streamNo), 00013 _buffer(NULL), _bufferOffset(0), _bufferSize(0), _running(false), _data(NULL), _dataOffset(0), _len(0), _playCursor(0), _writeCursor(0) 00014 { 00015 } 00016 00017 FFAudioDecoder::‾FFAudioDecoder() { 00018 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00019 stop(); 00020 SAFE_DELETE(_data); 00021 SAFE_RELEASE(_buffer); 00022 } 00023 00024 00025 bool FFAudioDecoder::isReady() { 00026 return true; 00027 } 00028 00029 void FFAudioDecoder::start() { 00030 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00031 AVCodecContext* avctx = _ic->streams[_streamNo]->codec; 00032 WORD sampleBit; 00033 string type; 00034 switch (avctx->sample_fmt) { 00035 case SAMPLE_FMT_U8: 00036 type = "unsigned 8 bits"; 00037 sampleBit = 8; 00038 break; 00039 case SAMPLE_FMT_S16: 00040 type = "signed 16 bits"; 00041 sampleBit = 16; 00042 break; 00043 case SAMPLE_FMT_S32: 00044 type = "signed 32 bits"; 00045 sampleBit = 32; 00046 break; 00047 case SAMPLE_FMT_FLT: 00048 type = "float"; 00049 sampleBit = 32; 00050 break; 00051 case SAMPLE_FMT_DBL: 00052 type = "double"; 00053 sampleBit = 32; 00054 break; 00055 default: 00056 type = Poco::format("unknown format(%d)", (int)avctx->sample_fmt); 00057 } 00058 _log.information(Poco::format("audio stream: format(%s) channels: %d sample: %hubit %dHz bitrate: %d", type, avctx->channels, sampleBit, avctx->sample_rate, avctx->bit_rate)); 00059 00060 //WAVEフォーマット設定 00061 WAVEFORMATEX wfwav; 00062 ZeroMemory(&wfwav, sizeof(wfwav)); 00063 wfwav.wFormatTag = WAVE_FORMAT_PCM; 00064 wfwav.nChannels = avctx->channels; 00065 wfwav.nSamplesPerSec = avctx->sample_rate; 00066 wfwav.wBitsPerSample = sampleBit; 00067 wfwav.nBlockAlign = wfwav.nChannels * wfwav.wBitsPerSample / 8; 00068 wfwav.nAvgBytesPerSec = wfwav.nSamplesPerSec * wfwav.nBlockAlign; 00069 wfwav.cbSize = 0; 00070 00071 _bufferSize = wfwav.nAvgBytesPerSec * 20; 00072 _bufferOffset = 0; 00073 _log.information(Poco::format("sound buffer size: %lu", _bufferSize)); 00074 00075 //プライマリバッファの作成 00076 DSBUFFERDESC desc; 00077 ZeroMemory(&desc, sizeof(desc)); 00078 desc.dwSize = sizeof(desc); 00079 // desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCDEFER | DSBCAPS_CTRLFREQUENCY; 00080 // desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCDEFER | DSBCAPS_CTRLPOSITIONNOTIFY; 00081 desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLVOLUME; 00082 desc.dwBufferBytes = _bufferSize; 00083 desc.lpwfxFormat = &wfwav; 00084 desc.guid3DAlgorithm = GUID_NULL; 00085 LPDIRECTSOUND sound = _renderer.getSoundDevice(); 00086 HRESULT hr = sound->CreateSoundBuffer(&desc, &_buffer, NULL); 00087 if (FAILED(hr)) { 00088 _log.warning("failed not create sound buffer"); 00089 00090 } else { 00091 hr = _buffer->SetCurrentPosition(0); 00092 // DWORD frq; 00093 // _buffer->GetFrequency(&frq); 00094 // _buffer->SetFrequency(frq * 1.25); 00095 _data = new uint8_t[BUFFER_SIZE]; 00096 ZeroMemory(_data, sizeof(uint8_t) * BUFFER_SIZE); 00097 } 00098 } 00099 00100 const UINT FFAudioDecoder::bufferedFrames() { 00101 return bufferedPackets(); 00102 } 00103 00104 void FFAudioDecoder::decode() { 00105 if (!_data) return; 00106 //_log.information("audio decoder thread start"); 00107 //DWORD threadAffinityMask = ::SetThreadAffinityMask(GetCurrentThread(), 1); 00108 if (_len > 0) return; 00109 if (_dataOffset > 0) return; 00110 AVPacketList* packetList = popPacket(); 00111 if (!packetList) return; 00112 00113 PerformanceTimer timer; 00114 timer.start(); 00115 AVCodecContext* avctx = _ic->streams[packetList->pkt.stream_index]->codec; 00116 AVPacket* packet = &packetList->pkt; 00117 AVPacket tmp; 00118 av_init_packet(&tmp); 00119 tmp.data = packet->data; 00120 tmp.size = packet->size; 00121 while (tmp.data && tmp.size > 0) { 00122 int frameSize = sizeof(uint8_t) * BUFFER_SIZE; 00123 int bytes = avcodec_decode_audio3(avctx, (int16_t*)(&_data[_len]), &frameSize, &tmp); 00124 if (bytes >= 0) { 00125 tmp.data += bytes; 00126 tmp.size -= bytes; 00127 if (frameSize > 0) { 00128 _len += frameSize; 00129 } 00130 _readTime = timer.getTime(); 00131 _readCount++; 00132 if (_readCount > 0) _avgTime = F(_avgTime * (_readCount - 1) + _readTime) / _readCount; 00133 00134 } else { 00135 // throw error or something? 00136 _log.warning(Poco::format("failed avcodec_decode_audio3: %d %d", bytes, frameSize)); 00137 _len = 0; 00138 break; 00139 } 00140 } 00141 if (packet->data) av_free_packet(packet); 00142 av_freep(&packetList); 00143 } 00144 00145 void FFAudioDecoder::writeData() { 00146 if (!_buffer) return; 00147 00148 HRESULT hr = _buffer->GetCurrentPosition(&_playCursor, &_writeCursor); 00149 if FAILED(hr) { 00150 _log.warning("failed get current position"); 00151 return; 00152 } 00153 if (_len <= 0) return; 00154 00155 if (_dataOffset > 0) { 00156 // 再生中で再生カーソルがバッファの半分以降になるまで書込み待ち 00157 // _log.information(Poco::format("buffer cursor: %lu %lu", _playCursor, (_bufferSize / 2))); 00158 if (!_running || _playCursor < _bufferSize / 2) return; 00159 00160 } else { 00161 // 書込みカーソル以降の場合、再生カーソルのデータx2個分余裕ができるまで書込み待ち 00162 if (_writeCursor > _bufferOffset && _playCursor < _bufferOffset + _len * 2) return; 00163 } 00164 00165 LPVOID lockedBuf = NULL; 00166 DWORD lockedLen = 0; 00167 if (_bufferOffset + _len <= _bufferSize) { 00168 // オフセット+データサイズがバッファ以下の場合はそのまますべて書込む 00169 hr = _buffer->Lock(_bufferOffset, _len, &lockedBuf, &lockedLen, NULL, 0, 0); 00170 if (SUCCEEDED(hr)) { 00171 CopyMemory(lockedBuf, &_data[_dataOffset], lockedLen); 00172 hr = _buffer->Unlock(lockedBuf, lockedLen, NULL, 0); 00173 if (FAILED(hr)) { 00174 _log.warning("failed unlocked sound buffer"); 00175 } else { 00176 _bufferOffset = (_bufferOffset + _len) % _bufferSize; 00177 _len = 0; 00178 _dataOffset = 0; 00179 } 00180 } else { 00181 _log.warning(Poco::format("sound buffer not locked: %d", _len)); 00182 } 00183 } else { 00184 // 残りバッファに書込みむ。残りは次回呼出し時に書込む 00185 //_log.information("round sound buffer"); 00186 int lenRound = _bufferSize - _bufferOffset; 00187 hr = _buffer->Lock(_bufferOffset, lenRound, &lockedBuf, &lockedLen, NULL, 0, 0); 00188 if (SUCCEEDED(hr)) { 00189 CopyMemory(lockedBuf, _data, lockedLen); 00190 hr = _buffer->Unlock(lockedBuf, lockedLen, NULL, 0); 00191 if (FAILED(hr)) { 00192 _log.warning("failed unlocked sound buffer"); 00193 } else { 00194 _bufferOffset = 0; 00195 _len -= lenRound; 00196 _dataOffset = lenRound; 00197 } 00198 } else { 00199 _log.warning(Poco::format("SoundBuffer not locked: %d", lenRound)); 00200 } 00201 } 00202 } 00203 00204 void FFAudioDecoder::finishedPacket() { 00205 if (!_buffer) return; 00206 00207 int size = _bufferSize - _bufferOffset; 00208 LPVOID lockedBuf = NULL; 00209 DWORD lockedLen = 0; 00210 HRESULT hr = _buffer->Lock(_bufferOffset, size, &lockedBuf, &lockedLen, NULL, 0, 0); 00211 if (SUCCEEDED(hr)) { 00212 ZeroMemory(lockedBuf, lockedLen); 00213 hr = _buffer->Unlock(lockedBuf, lockedLen, NULL, 0); 00214 } 00215 } 00216 00217 bool FFAudioDecoder::playing() { 00218 return _running; 00219 } 00220 00221 void FFAudioDecoder::play() { 00222 if (_buffer && !_running) { 00223 HRESULT hr = _buffer->Play(0, 0, DSBPLAY_LOOPING); 00224 if (SUCCEEDED(hr)) { 00225 _running = true; 00226 } else { 00227 _log.warning("failed play sound buffer"); 00228 } 00229 } 00230 } 00231 00232 void FFAudioDecoder::stop() { 00233 if (_buffer && _running) { 00234 HRESULT hr = _buffer->Stop(); 00235 if (SUCCEEDED(hr)) { 00236 _running = false; 00237 } 00238 } 00239 } 00240 00241 #endif