Changeset 2288 for pjproject/trunk


Ignore:
Timestamp:
Sep 17, 2008 11:56:44 AM (16 years ago)
Author:
bennylp
Message:

Ticket #633: Updated DirectSound? implementation:

  • Fixed issue on start/stop without close/reopen.
  • Fixed possibility of buffer overrun whe 10ms samples used.
  • Fixed latency unit of sound stream info, from ms to samples.
  • Updated playback buffer to fill the whole playback buffer in each notification in order to increase samples data availability.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia/dsound.c

    r2286 r2288  
    3939 
    4040 
    41  
    4241#define THIS_FILE           "dsound.c" 
    4342#define BITS_PER_SAMPLE     16 
     
    114113 
    115114    pj_thread_t            *thread;             /**< Thread handle.         */ 
    116     pj_bool_t               thread_quit_flag;   /**< Quit signal to thread  */ 
     115    HANDLE                  thread_quit_event;  /**< Quit signal to thread  */ 
    117116}; 
    118117 
     
    433432} 
    434433 
    435  
    436 /* 
    437  * Check if there are captured frames in DirectSound capture buffer. 
    438  */ 
    439 static unsigned dsound_captured_size(struct dsound_stream *dsound_strm) 
     434/* 
     435 * Check if there is space in playing buffer. 
     436 */ 
     437static unsigned dsound_play_empty_size(struct dsound_stream *dsound_strm) 
    440438{ 
    441439    HRESULT hr; 
     
    443441    DWORD writePos, readPos; 
    444442 
    445     hr = IDirectSoundCaptureBuffer_GetCurrentPosition(dsound_strm->ds.capture.lpDsBuffer,  
    446                                                       &writePos, &readPos); 
     443    hr = IDirectSoundBuffer_GetCurrentPosition(dsound_strm->ds.play.lpDsBuffer,  
     444                                               &readPos, &writePos); 
     445    if FAILED(hr) 
     446        return PJ_FALSE; 
     447 
     448    if (readPos < dsound_strm->dwBytePos) 
     449        size_available = readPos + dsound_strm->dwDsBufferSize -  
     450                         dsound_strm->dwBytePos; 
     451    else 
     452        size_available = readPos - dsound_strm->dwBytePos; 
     453 
     454    return size_available; 
     455} 
     456 
     457 
     458/* 
     459 * Check if there are captured frames in DirectSound capture buffer. 
     460 */ 
     461static unsigned dsound_captured_size(struct dsound_stream *dsound_strm) 
     462{ 
     463    HRESULT hr; 
     464    long size_available; 
     465    DWORD writePos, readPos; 
     466 
     467    hr = IDirectSoundCaptureBuffer_GetCurrentPosition( 
     468                                        dsound_strm->ds.capture.lpDsBuffer,  
     469                                        &writePos, &readPos); 
    447470    if FAILED(hr) 
    448471        return PJ_FALSE; 
     
    463486{ 
    464487    pjmedia_snd_stream *strm = arg; 
    465     HANDLE events[2]; 
     488    HANDLE events[3]; 
    466489    unsigned eventCount; 
    467490    unsigned bytes_per_frame; 
     
    470493 
    471494    eventCount = 0; 
     495    events[eventCount++] = strm->thread_quit_event; 
    472496    if (strm->dir & PJMEDIA_DIR_PLAYBACK) 
    473497        events[eventCount++] = strm->play_strm.hEvent; 
     
    479503     * system activity. 
    480504     */ 
    481     //SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST); 
     505    SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST); 
    482506 
    483507    /* Calculate bytes per frame */ 
     
    488512     * signalled by DirectSound capture and play buffer. 
    489513     */ 
    490     while (!strm->thread_quit_flag) { 
     514    while (PJ_TRUE) { 
    491515         
    492516        DWORD rc; 
    493517        pjmedia_dir signalled_dir; 
    494518 
    495         rc = WaitForMultipleObjects(eventCount, events, FALSE,  
    496                                     100); 
     519        rc = WaitForMultipleObjects(eventCount, events, FALSE, INFINITE); 
    497520        if (rc < WAIT_OBJECT_0 || rc >= WAIT_OBJECT_0+eventCount) 
    498521            continue; 
    499522 
    500523 
    501         if (rc == WAIT_OBJECT_0) { 
    502             if (events[0] == strm->play_strm.hEvent) 
    503                 signalled_dir = PJMEDIA_DIR_PLAYBACK; 
     524        if (rc == WAIT_OBJECT_0) 
     525                break; 
     526        if (rc == (WAIT_OBJECT_0 + 1)) { 
     527            if (events[1] == strm->play_strm.hEvent) 
     528                signalled_dir = PJMEDIA_DIR_PLAYBACK; 
    504529            else 
    505                 signalled_dir = PJMEDIA_DIR_CAPTURE; 
     530                signalled_dir = PJMEDIA_DIR_CAPTURE; 
    506531        } else { 
    507             if (events[1] == strm->play_strm.hEvent) 
    508                 signalled_dir = PJMEDIA_DIR_PLAYBACK; 
     532            if (events[2] == strm->play_strm.hEvent) 
     533                signalled_dir = PJMEDIA_DIR_PLAYBACK; 
    509534            else 
    510                 signalled_dir = PJMEDIA_DIR_CAPTURE; 
     535                signalled_dir = PJMEDIA_DIR_CAPTURE; 
    511536        } 
    512537 
     
    524549            status = PJ_SUCCESS; 
    525550 
    526             /* Get frame from application. */ 
    527             status = (*strm->play_cb)(strm->user_data,  
    528                                       dsound_strm->timestamp.u32.lo, 
    529                                       strm->buffer, 
     551            while (dsound_play_empty_size(dsound_strm) > bytes_per_frame) { 
     552                /* Get frame from application. */ 
     553                status = (*strm->play_cb)(strm->user_data,  
     554                                          dsound_strm->timestamp.u32.lo, 
     555                                          strm->buffer, 
     556                                          bytes_per_frame); 
     557                if (status != PJ_SUCCESS) 
     558                    break; 
     559 
     560                /* Write to DirectSound buffer. */ 
     561                AppWriteDataToBuffer( dsound_strm->ds.play.lpDsBuffer,  
     562                                      dsound_strm->dwBytePos, 
     563                                      (LPBYTE)strm->buffer,  
    530564                                      bytes_per_frame); 
    531             if (status != PJ_SUCCESS) 
    532                 break; 
    533  
    534             /* Write to DirectSound buffer. */ 
    535             AppWriteDataToBuffer( dsound_strm->ds.play.lpDsBuffer,  
    536                                   dsound_strm->dwBytePos, 
    537                                   (LPBYTE)strm->buffer,  
    538                                   bytes_per_frame); 
    539  
    540             /* Increment position. */ 
    541             dsound_strm->dwBytePos += bytes_per_frame; 
    542             if (dsound_strm->dwBytePos >= dsound_strm->dwDsBufferSize) 
    543                 dsound_strm->dwBytePos -= dsound_strm->dwDsBufferSize; 
    544             dsound_strm->timestamp.u64 += strm->samples_per_frame; 
     565 
     566                /* Increment position. */ 
     567                dsound_strm->dwBytePos += bytes_per_frame; 
     568                if (dsound_strm->dwBytePos >= dsound_strm->dwDsBufferSize) 
     569                    dsound_strm->dwBytePos -= dsound_strm->dwDsBufferSize; 
     570                dsound_strm->timestamp.u64 += strm->samples_per_frame; 
     571            } 
    545572 
    546573        } else { 
     
    555582            dsound_strm = &strm->rec_strm; 
    556583 
    557             do { 
     584            /* Fetch while we have more than 1 frame */ 
     585            while (dsound_captured_size(dsound_strm) > bytes_per_frame) { 
     586 
    558587                /* Capture from DirectSound buffer. */ 
    559588                rc = AppReadDataFromBuffer(dsound_strm->ds.capture.lpDsBuffer,  
     
    561590                                           (LPBYTE)strm->buffer,  
    562591                                           bytes_per_frame); 
    563                  
     592                 
    564593                if (!rc) { 
    565594                    pj_bzero(strm->buffer, bytes_per_frame); 
     
    582611                    dsound_strm->dwBytePos -= dsound_strm->dwDsBufferSize; 
    583612                dsound_strm->timestamp.u64 += strm->samples_per_frame; 
    584  
    585                 /* Fetch while we have more than 1 frame */ 
    586             } while (dsound_captured_size(dsound_strm) > bytes_per_frame); 
    587  
     613            } 
    588614        } 
    589615    } 
     
    628654 
    629655#ifdef UNICODE 
    630     WideCharToMultiByte(CP_ACP, 0, lpcstrDescription, wcslen(lpcstrDescription), dev_info[index].info.name, max, NULL, NULL); 
     656    WideCharToMultiByte(CP_ACP, 0, lpcstrDescription, wcslen(lpcstrDescription), 
     657                        dev_info[index].info.name, max, NULL, NULL); 
    631658#else 
    632659    strncpy(dev_info[index].info.name, lpcstrDescription, max); 
     
    768795    } 
    769796 
     797    /* 
     798     * Create event for stopping the worker thread. 
     799     */ 
     800    strm->thread_quit_event = CreateEvent(NULL, FALSE, FALSE, NULL); 
     801    if (strm->thread_quit_event == NULL) { 
     802        status = pj_get_os_error(); 
     803        pj_pool_release(pool); 
     804        return status; 
     805    } 
     806 
    770807    /* Create player stream */ 
    771808    if (dir & PJMEDIA_DIR_PLAYBACK) { 
     
    900937    pi->samples_per_frame = strm->samples_per_frame; 
    901938    pi->bits_per_sample = strm->bits_per_sample; 
    902     pi->rec_latency = strm->rec_strm.latency; 
    903     pi->play_latency = strm->play_strm.latency; 
     939    pi->rec_latency = strm->rec_strm.latency * strm->clock_rate *  
     940                      strm->channel_count/ 1000; 
     941    pi->play_latency = strm->play_strm.latency * strm->clock_rate *  
     942                       strm->channel_count/ 1000; 
    904943 
    905944    return PJ_SUCCESS; 
     
    914953    HRESULT hr; 
    915954 
    916     PJ_UNUSED_ARG(stream); 
    917  
    918955    if (stream->play_strm.ds.play.lpDsBuffer) { 
     956        hr = IDirectSoundBuffer_SetCurrentPosition( 
     957                                stream->play_strm.ds.play.lpDsBuffer, 0); 
     958        if (FAILED(hr)) 
     959            return PJ_RETURN_OS_ERROR(hr); 
     960         
     961        stream->play_strm.dwBytePos = 0; 
     962 
    919963        hr = IDirectSoundBuffer_Play(stream->play_strm.ds.play.lpDsBuffer,  
    920964                                     0, 0, DSBPLAY_LOOPING); 
     
    925969     
    926970    if (stream->rec_strm.ds.capture.lpDsBuffer) { 
    927         hr = IDirectSoundCaptureBuffer_Start(stream->rec_strm.ds.capture.lpDsBuffer, 
    928                                              DSCBSTART_LOOPING ); 
     971        hr = IDirectSoundCaptureBuffer_GetCurrentPosition(  
     972                                stream->rec_strm.ds.capture.lpDsBuffer,  
     973                                NULL, &stream->rec_strm.dwBytePos ); 
     974        if (FAILED(hr)) 
     975            return PJ_RETURN_OS_ERROR(hr); 
     976 
     977        hr = IDirectSoundCaptureBuffer_Start( 
     978                                stream->rec_strm.ds.capture.lpDsBuffer, 
     979                                DSCBSTART_LOOPING ); 
    929980        if (FAILED(hr)) 
    930981            return PJ_RETURN_OS_ERROR(hr); 
     
    9661017 
    9671018    if (stream->thread) { 
    968         stream->thread_quit_flag = 1; 
     1019        pj_assert(stream->thread_quit_event); 
     1020        SetEvent(stream->thread_quit_event); 
    9691021        pj_thread_join(stream->thread); 
    9701022        pj_thread_destroy(stream->thread); 
    9711023        stream->thread = NULL; 
     1024    } 
     1025 
     1026    if (stream->thread_quit_event) { 
     1027        CloseHandle(stream->thread_quit_event); 
     1028        stream->thread_quit_event = NULL; 
    9721029    } 
    9731030 
Note: See TracChangeset for help on using the changeset viewer.