- Timestamp:
- Feb 22, 2009 5:15:34 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/wmme_dev.c
r2469 r2470 31 31 #include <windows.h> 32 32 #include <mmsystem.h> 33 #include <mmreg.h> 33 34 34 35 #ifdef _MSC_VER … … 103 104 void *buffer; /**< Temp. frame buffer. */ 104 105 unsigned clock_rate; /**< Clock rate. */ 106 unsigned bytes_per_frame; /**< Bytes per frame */ 105 107 unsigned samples_per_frame; /**< Samples per frame. */ 106 108 unsigned bits_per_sample; /**< Bits per sample. */ 107 109 unsigned channel_count; /**< Channel count. */ 110 111 pjmedia_frame_ext *xfrm; /**< Extended frame buffer */ 112 unsigned xfrm_size; /**< Total ext frm size */ 108 113 109 114 pj_thread_t *thread; /**< Thread handle. */ … … 193 198 /* Internal: build device info from WAVEINCAPS/WAVEOUTCAPS */ 194 199 static void build_dev_info(UINT deviceId, struct wmme_dev_info *wdi, 195 WAVEINCAPS *wic,WAVEOUTCAPS *woc)200 const WAVEINCAPS *wic, const WAVEOUTCAPS *woc) 196 201 { 197 202 #define WIC_WOC(wic,woc,field) (wic? wic->field : woc->field) … … 205 210 wdi->info.name[sizeof(wdi->info.name)-1] = '\0'; 206 211 } else { 207 pj_char_t *szPname = WIC_WOC(wic, woc, szPname);212 const pj_char_t *szPname = WIC_WOC(wic, woc, szPname); 208 213 PJ_DECL_ANSI_TEMP_BUF(wTmp, sizeof(wdi->info.name)); 209 214 … … 246 251 } 247 252 } 253 254 /* Extended formats */ 255 wdi->info.caps |= PJMEDIA_AUD_DEV_CAP_EXT_FORMAT; 256 wdi->info.ext_fmt_cnt = 2; 257 wdi->info.ext_fmt[0].id = PJMEDIA_FORMAT_PCMU; 258 wdi->info.ext_fmt[0].bitrate = 64000; 259 wdi->info.ext_fmt[0].vad = 0; 260 wdi->info.ext_fmt[1].id = PJMEDIA_FORMAT_PCMA; 261 wdi->info.ext_fmt[1].bitrate = 64000; 262 wdi->info.ext_fmt[1].vad = 0; 248 263 } 249 264 … … 280 295 sizeof(struct wmme_dev_info)); 281 296 282 if ( devCount) {297 if (inputDeviceCount && outputDeviceCount) { 283 298 /* Attempt to add WAVE_MAPPER as input and output device */ 284 299 WAVEINCAPS wic; … … 435 450 436 451 /* Internal: init WAVEFORMATEX */ 437 static void init_waveformatex (LPWAVEFORMATEX pcmwf, 438 unsigned clock_rate, 439 unsigned channel_count) 440 { 441 pj_bzero(pcmwf, sizeof(PCMWAVEFORMAT)); 442 pcmwf->wFormatTag = WAVE_FORMAT_PCM; 443 pcmwf->nChannels = (pj_uint16_t)channel_count; 444 pcmwf->nSamplesPerSec = clock_rate; 445 pcmwf->nBlockAlign = (pj_uint16_t)(channel_count * BYTES_PER_SAMPLE); 446 pcmwf->nAvgBytesPerSec = clock_rate * channel_count * BYTES_PER_SAMPLE; 447 pcmwf->wBitsPerSample = BITS_PER_SAMPLE; 452 static pj_status_t init_waveformatex(LPWAVEFORMATEX wfx, 453 const pjmedia_aud_param *prm) 454 { 455 456 pj_bzero(wfx, sizeof(PCMWAVEFORMAT)); 457 if (prm->ext_fmt.id == PJMEDIA_FORMAT_L16) { 458 wfx->wFormatTag = WAVE_FORMAT_PCM; 459 wfx->nChannels = (pj_uint16_t)prm->channel_count; 460 wfx->nSamplesPerSec = prm->clock_rate; 461 wfx->nBlockAlign = (pj_uint16_t)(prm->channel_count * 462 BYTES_PER_SAMPLE); 463 wfx->nAvgBytesPerSec = prm->clock_rate * prm->channel_count * 464 BYTES_PER_SAMPLE; 465 wfx->wBitsPerSample = BITS_PER_SAMPLE; 466 467 return PJ_SUCCESS; 468 469 } else if ((prm->flags & PJMEDIA_AUD_DEV_CAP_EXT_FORMAT) && 470 (prm->ext_fmt.id == PJMEDIA_FORMAT_PCMA || 471 prm->ext_fmt.id == PJMEDIA_FORMAT_PCMU)) 472 { 473 unsigned ptime; 474 475 ptime = prm->samples_per_frame * 1000 / 476 (prm->clock_rate * prm->channel_count); 477 wfx->wFormatTag = (pj_uint16_t) 478 ((prm->ext_fmt.id==PJMEDIA_FORMAT_PCMA) ? 479 WAVE_FORMAT_ALAW : WAVE_FORMAT_MULAW); 480 wfx->nChannels = (pj_uint16_t)prm->channel_count; 481 wfx->nSamplesPerSec = prm->clock_rate; 482 wfx->nAvgBytesPerSec = prm->clock_rate * prm->channel_count; 483 wfx->nBlockAlign = (pj_uint16_t)(wfx->nAvgBytesPerSec * ptime / 484 1000); 485 wfx->wBitsPerSample = 8; 486 wfx->cbSize = 0; 487 488 return PJ_SUCCESS; 489 490 } else { 491 492 return PJMEDIA_EAUD_BADFORMAT; 493 494 } 448 495 } 449 496 … … 452 499 static pj_status_t init_player_stream( struct wmme_factory *wf, 453 500 pj_pool_t *pool, 501 struct wmme_stream *parent, 454 502 struct wmme_channel *wmme_strm, 455 unsigned dev_id, 456 unsigned clock_rate, 457 unsigned channel_count, 458 unsigned samples_per_frame, 503 const pjmedia_aud_param *prm, 459 504 unsigned buffer_count) 460 505 { 461 506 MMRESULT mr; 462 WAVEFORMATEX pcmwf;463 unsigned bytes_per_frame;464 unsigned i;465 466 PJ_ASSERT_RETURN( dev_id <wf->dev_count, PJ_EINVAL);507 WAVEFORMATEX wfx; 508 unsigned i, ptime; 509 pj_status_t status; 510 511 PJ_ASSERT_RETURN(prm->play_id < (int)wf->dev_count, PJ_EINVAL); 467 512 468 513 /* … … 476 521 * Set up wave format structure for opening the device. 477 522 */ 478 init_waveformatex(&pcmwf, clock_rate, channel_count); 479 bytes_per_frame = samples_per_frame * BYTES_PER_SAMPLE; 523 status = init_waveformatex(&wfx, prm); 524 if (status != PJ_SUCCESS) 525 return status; 526 527 ptime = prm->samples_per_frame * 1000 / 528 (prm->clock_rate * prm->channel_count); 529 ptime = prm->samples_per_frame * 1000 / 530 (prm->clock_rate * prm->channel_count); 531 parent->bytes_per_frame = wfx.nAvgBytesPerSec / ptime; 480 532 481 533 /* 482 534 * Open wave device. 483 535 */ 484 mr = waveOutOpen(&wmme_strm->hWave.Out, wf->dev_info[dev_id].deviceId, 485 &pcmwf, (DWORD)wmme_strm->hEvent, 0, CALLBACK_EVENT); 536 mr = waveOutOpen(&wmme_strm->hWave.Out, 537 wf->dev_info[prm->play_id].deviceId, 538 &wfx, (DWORD)wmme_strm->hEvent, 0, CALLBACK_EVENT); 486 539 if (mr != MMSYSERR_NOERROR) { 487 540 return CONVERT_MM_ERROR(mr); … … 500 553 pj_pool_zalloc(pool, sizeof(WAVEHDR) * buffer_count); 501 554 for (i = 0; i < buffer_count; ++i) { 502 wmme_strm->WaveHdr[i].lpData = pj_pool_zalloc(pool, bytes_per_frame); 503 wmme_strm->WaveHdr[i].dwBufferLength = bytes_per_frame; 555 wmme_strm->WaveHdr[i].lpData = pj_pool_zalloc(pool, 556 parent->bytes_per_frame); 557 wmme_strm->WaveHdr[i].dwBufferLength = parent->bytes_per_frame; 504 558 mr = waveOutPrepareHeader(wmme_strm->hWave.Out, 505 559 &(wmme_strm->WaveHdr[i]), … … 523 577 " WaveAPI Sound player \"%s\" initialized (clock_rate=%d, " 524 578 "channel_count=%d, samples_per_frame=%d (%dms))", 525 wf->dev_info[ dev_id].info.name,526 clock_rate, channel_count,samples_per_frame,527 samples_per_frame * 1000 /clock_rate));579 wf->dev_info[prm->play_id].info.name, 580 prm->clock_rate, prm->channel_count, prm->samples_per_frame, 581 prm->samples_per_frame * 1000 / prm->clock_rate)); 528 582 529 583 return PJ_SUCCESS; … … 534 588 static pj_status_t init_capture_stream( struct wmme_factory *wf, 535 589 pj_pool_t *pool, 590 struct wmme_stream *parent, 536 591 struct wmme_channel *wmme_strm, 537 unsigned dev_id, 538 unsigned clock_rate, 539 unsigned channel_count, 540 unsigned samples_per_frame, 592 const pjmedia_aud_param *prm, 541 593 unsigned buffer_count) 542 594 { 543 595 MMRESULT mr; 544 WAVEFORMATEX pcmwf; 545 unsigned bytes_per_frame; 546 unsigned i; 547 548 PJ_ASSERT_RETURN(dev_id < wf->dev_count, PJ_EINVAL); 596 WAVEFORMATEX wfx; 597 unsigned i, ptime; 598 599 PJ_ASSERT_RETURN(prm->rec_id < (int)wf->dev_count, PJ_EINVAL); 549 600 550 601 /* … … 559 610 * Set up wave format structure for opening the device. 560 611 */ 561 init_waveformatex(&pcmwf, clock_rate, channel_count); 562 bytes_per_frame = samples_per_frame * BYTES_PER_SAMPLE; 612 init_waveformatex(&wfx, prm); 613 ptime = prm->samples_per_frame * 1000 / 614 (prm->clock_rate * prm->channel_count); 615 parent->bytes_per_frame = wfx.nAvgBytesPerSec / ptime; 563 616 564 617 /* 565 618 * Open wave device. 566 619 */ 567 mr = waveInOpen(&wmme_strm->hWave.In, wf->dev_info[dev_id].deviceId, 568 &pcmwf, (DWORD)wmme_strm->hEvent, 0, CALLBACK_EVENT); 620 mr = waveInOpen(&wmme_strm->hWave.In, 621 wf->dev_info[prm->rec_id].deviceId, 622 &wfx, (DWORD)wmme_strm->hEvent, 0, CALLBACK_EVENT); 569 623 if (mr != MMSYSERR_NOERROR) { 570 624 return CONVERT_MM_ERROR(mr); … … 577 631 pj_pool_zalloc(pool, sizeof(WAVEHDR) * buffer_count); 578 632 for (i = 0; i < buffer_count; ++i) { 579 wmme_strm->WaveHdr[i].lpData = pj_pool_zalloc(pool, bytes_per_frame); 580 wmme_strm->WaveHdr[i].dwBufferLength = bytes_per_frame; 633 wmme_strm->WaveHdr[i].lpData = pj_pool_zalloc(pool, 634 parent->bytes_per_frame); 635 wmme_strm->WaveHdr[i].dwBufferLength = parent->bytes_per_frame; 581 636 mr = waveInPrepareHeader(wmme_strm->hWave.In, 582 637 &(wmme_strm->WaveHdr[i]), … … 600 655 " WaveAPI Sound recorder \"%s\" initialized (clock_rate=%d, " 601 656 "channel_count=%d, samples_per_frame=%d (%dms))", 602 wf->dev_info[ dev_id].info.name,603 clock_rate, channel_count,samples_per_frame,604 samples_per_frame * 1000 /clock_rate));657 wf->dev_info[prm->rec_id].info.name, 658 prm->clock_rate, prm->channel_count, prm->samples_per_frame, 659 prm->samples_per_frame * 1000 / prm->clock_rate)); 605 660 606 661 return PJ_SUCCESS; … … 614 669 HANDLE events[3]; 615 670 unsigned eventCount; 616 unsigned bytes_per_frame;617 671 pj_status_t status = PJ_SUCCESS; 618 619 672 620 673 eventCount = 0; … … 638 691 #endif 639 692 640 /* Calculate bytes per frame */641 bytes_per_frame = strm->samples_per_frame * BYTES_PER_SAMPLE;642 643 693 /* 644 694 * Loop while not signalled to quit, wait for event objects to be … … 677 727 { 678 728 struct wmme_channel *wmme_strm = &strm->play_strm; 679 MMRESULT mr = MMSYSERR_NOERROR; 729 680 730 status = PJ_SUCCESS; 681 731 … … 688 738 { 689 739 void *buffer = wmme_strm->WaveHdr[wmme_strm->dwBufIdx].lpData; 690 pjmedia_frame frame; 740 pjmedia_frame pcm_frame, *frame; 741 pj_bool_t has_frame = PJ_FALSE; 691 742 692 743 //PJ_LOG(5,(THIS_FILE, "Finished writing buffer %d", 693 744 // wmme_strm->dwBufIdx)); 694 745 695 frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 696 frame.size = bytes_per_frame; 697 frame.buf = buffer; 698 frame.timestamp.u64 = wmme_strm->timestamp.u64; 699 frame.bit_info = 0; 746 if (strm->xfrm == NULL) { 747 /* PCM mode */ 748 frame = &pcm_frame; 749 750 frame->type = PJMEDIA_FRAME_TYPE_AUDIO; 751 frame->size = strm->bytes_per_frame; 752 frame->buf = buffer; 753 frame->timestamp.u64 = wmme_strm->timestamp.u64; 754 frame->bit_info = 0; 755 } else { 756 /* Codec mode */ 757 frame = &strm->xfrm->base; 758 759 strm->xfrm->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 760 strm->xfrm->base.size = strm->bytes_per_frame; 761 strm->xfrm->base.buf = NULL; 762 strm->xfrm->base.timestamp.u64 = wmme_strm->timestamp.u64; 763 strm->xfrm->base.bit_info = 0; 764 } 700 765 701 766 /* Get frame from application. */ 702 status = (*strm->play_cb)(strm->user_data, &frame);767 status = (*strm->play_cb)(strm->user_data, frame); 703 768 704 769 if (status != PJ_SUCCESS) 705 770 break; 706 771 707 if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO) { 708 pj_bzero(buffer, bytes_per_frame); 772 if (strm->xfrm == NULL) { 773 /* PCM mode */ 774 if (frame->type == PJMEDIA_FRAME_TYPE_NONE) { 775 pj_bzero(buffer, strm->bytes_per_frame); 776 has_frame = PJ_TRUE; 777 } else if (frame->type == PJMEDIA_FRAME_TYPE_EXTENDED) { 778 pj_assert(!"Frame type not supported"); 779 } else if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO) { 780 has_frame = PJ_TRUE; 781 } else { 782 pj_assert(!"Frame type not supported"); 783 } 784 } else { 785 /* Codec mode */ 786 if (frame->type == PJMEDIA_FRAME_TYPE_NONE) { 787 /* Not supported */ 788 } else if (frame->type == PJMEDIA_FRAME_TYPE_EXTENDED) { 789 unsigned sz; 790 sz = pjmedia_frame_ext_copy_payload(strm->xfrm, 791 buffer, 792 strm->bytes_per_frame); 793 pj_assert(sz == strm->bytes_per_frame); 794 } else { 795 pj_assert(!"Frame type not supported"); 796 } 709 797 } 710 798 711 799 /* Write to the device. */ 712 mr = waveOutWrite(wmme_strm->hWave.Out, 713 &(wmme_strm->WaveHdr[wmme_strm->dwBufIdx]), 714 sizeof(WAVEHDR)); 715 if (mr != MMSYSERR_NOERROR) 716 { 717 status = CONVERT_MM_ERROR(mr); 718 break; 800 if (has_frame) { 801 MMRESULT mr = MMSYSERR_NOERROR; 802 803 mr = waveOutWrite(wmme_strm->hWave.Out, 804 &(wmme_strm->WaveHdr[wmme_strm->dwBufIdx]), 805 sizeof(WAVEHDR)); 806 if (mr != MMSYSERR_NOERROR) { 807 status = CONVERT_MM_ERROR(mr); 808 break; 809 } 719 810 } 720 811 … … 766 857 unsigned cap_len = 767 858 wmme_strm->WaveHdr[wmme_strm->dwBufIdx].dwBytesRecorded; 768 pjmedia_frame frame;859 pjmedia_frame pcm_frame, *frame; 769 860 770 861 /* … … 772 863 wmme_strm->dwBufIdx)); 773 864 */ 774 775 if (cap_len < bytes_per_frame) 776 pj_bzero(buffer + cap_len, bytes_per_frame - cap_len); 777 778 /* Copy the audio data out of the wave buffer. */ 779 pj_memcpy(strm->buffer, buffer, bytes_per_frame); 865 866 if (strm->xfrm == NULL) { 867 /* PCM mode */ 868 if (cap_len < strm->bytes_per_frame) 869 pj_bzero(buffer + cap_len, 870 strm->bytes_per_frame - cap_len); 871 872 /* Copy the audio data out of the wave buffer. */ 873 pj_memcpy(strm->buffer, buffer, strm->bytes_per_frame); 874 875 /* Prepare frame */ 876 frame = &pcm_frame; 877 frame->type = PJMEDIA_FRAME_TYPE_AUDIO; 878 frame->buf = strm->buffer; 879 frame->size = strm->bytes_per_frame; 880 frame->timestamp.u64 = wmme_strm->timestamp.u64; 881 frame->bit_info = 0; 882 883 } else { 884 /* Codec mode */ 885 frame = &strm->xfrm->base; 886 887 frame->type = PJMEDIA_FRAME_TYPE_EXTENDED; 888 frame->buf = NULL; 889 frame->size = strm->bytes_per_frame; 890 frame->timestamp.u64 = wmme_strm->timestamp.u64; 891 frame->bit_info = 0; 892 893 strm->xfrm->samples_cnt = 0; 894 strm->xfrm->subframe_cnt = 0; 895 pjmedia_frame_ext_append_subframe(strm->xfrm, buffer, 896 strm->bytes_per_frame *8, 897 strm->samples_per_frame); 898 } 780 899 781 900 /* Re-add the buffer to the device. */ … … 788 907 } 789 908 790 /* Prepare frame */791 frame.type = PJMEDIA_FRAME_TYPE_AUDIO;792 frame.buf = strm->buffer;793 frame.size = bytes_per_frame;794 frame.timestamp.u64 = wmme_strm->timestamp.u64;795 frame.bit_info = 0;796 909 797 910 /* Call callback */ 798 status = (*strm->rec_cb)(strm->user_data, &frame);911 status = (*strm->rec_cb)(strm->user_data, frame); 799 912 if (status != PJ_SUCCESS) 800 913 break; … … 866 979 867 980 status = init_player_stream(wf, strm->pool, 981 strm, 868 982 &strm->play_strm, 869 param->play_id, 870 param->clock_rate, 871 param->channel_count, 872 param->samples_per_frame, 983 param, 873 984 buf_count); 874 985 … … 892 1003 893 1004 status = init_capture_stream(wf, strm->pool, 1005 strm, 894 1006 &strm->rec_strm, 895 param->rec_id, 896 param->clock_rate, 897 param->channel_count, 898 param->samples_per_frame, 1007 param, 899 1008 buf_count); 900 1009 … … 903 1012 return status; 904 1013 } 1014 } 1015 1016 /* If format is extended, must create buffer for the extended frame. */ 1017 if (param->ext_fmt.id != PJMEDIA_FORMAT_L16) { 1018 unsigned ptime = param->samples_per_frame * 1000 / 1019 (param->clock_rate * param->channel_count); 1020 strm->xfrm_size = sizeof(pjmedia_frame_ext) + 1021 32 * sizeof(pjmedia_frame_ext_subframe) + 1022 (8000 * ptime / 1000) + 4; 1023 strm->xfrm = (pjmedia_frame_ext*) 1024 pj_pool_alloc(pool, strm->xfrm_size); 905 1025 } 906 1026
Note: See TracChangeset
for help on using the changeset viewer.