- Timestamp:
- May 6, 2009 3:44:12 PM (16 years ago)
- Location:
- pjproject/trunk/pjmedia/src/pjmedia-audiodev
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp
r2506 r2677 21 21 #include <pjmedia-audiodev/errno.h> 22 22 #include <pjmedia/alaw_ulaw.h> 23 #include <pjmedia/resample.h> 24 #include <pjmedia/stereo.h> 23 25 #include <pj/assert.h> 24 26 #include <pj/log.h> … … 81 83 82 84 // Common settings. 83 pjmedia_aud_param param;/**< Stream param. */85 pjmedia_aud_param param; /**< Stream param. */ 84 86 pjmedia_aud_rec_cb rec_cb; /**< Record callback. */ 85 87 pjmedia_aud_play_cb play_cb; /**< Playback callback. */ … … 98 100 pj_uint16_t rec_buf_len; /**< Record buffer length. */ 99 101 void *strm_data; /**< Stream data. */ 102 103 /* Resampling is needed, in case audio device is opened with clock rate 104 * other than 8kHz (only for PCM format). 105 */ 106 pjmedia_resample *play_resample; /**< Resampler for playback. */ 107 pjmedia_resample *rec_resample; /**< Resampler for recording */ 108 pj_uint16_t resample_factor; /**< Resample factor, requested 109 clock rate / 8000 */ 110 111 /* When stream is working in PCM format, where the samples may need to be 112 * resampled from/to different clock rate and/or channel count, PCM buffer 113 * is needed to perform such resampling operations. 114 */ 115 pj_int16_t *pcm_buf; /**< PCM buffer. */ 100 116 }; 101 117 … … 678 694 } 679 695 680 696 /**************************************************************************** 697 * Internal APS callbacks for PCM format 698 */ 681 699 682 700 static void RecCbPcm(TAPSCommBuffer &buf, void *user_data) … … 699 717 * Whenever rec_buf is full, call parent stream callback. 700 718 */ 701 unsigned dec_len = 0; 702 703 while (dec_len < aps_g711_frame_len) { 704 unsigned tmp; 705 706 tmp = PJ_MIN(strm->param.samples_per_frame - strm->rec_buf_len, 707 aps_g711_frame_len - dec_len); 719 unsigned samples_processed = 0; 720 721 while (samples_processed < aps_g711_frame_len) { 722 unsigned samples_to_process; 723 unsigned samples_req; 724 725 samples_to_process = aps_g711_frame_len - samples_processed; 726 samples_req = (strm->param.samples_per_frame / 727 strm->param.channel_count / 728 strm->resample_factor) - 729 strm->rec_buf_len; 730 if (samples_to_process > samples_req) 731 samples_to_process = samples_req; 732 708 733 pjmedia_ulaw_decode(&strm->rec_buf[strm->rec_buf_len], 709 buf.iBuffer.Ptr() + 2 + dec_len, 710 tmp); 711 strm->rec_buf_len += tmp; 712 dec_len += tmp; 713 714 pj_assert(strm->rec_buf_len <= strm->param.samples_per_frame); 715 716 if (strm->rec_buf_len == strm->param.samples_per_frame) { 734 buf.iBuffer.Ptr() + 2 + samples_processed, 735 samples_to_process); 736 737 strm->rec_buf_len += samples_to_process; 738 samples_processed += samples_to_process; 739 740 /* Buffer is full, time to call parent callback */ 741 if (strm->rec_buf_len == strm->param.samples_per_frame / 742 strm->param.channel_count / 743 strm->resample_factor) 744 { 717 745 pjmedia_frame f; 718 746 747 /* Need to resample clock rate? */ 748 if (strm->rec_resample) { 749 unsigned resampled = 0; 750 751 while (resampled < strm->rec_buf_len) { 752 pjmedia_resample_run(strm->rec_resample, 753 &strm->rec_buf[resampled], 754 strm->pcm_buf + 755 resampled * strm->resample_factor); 756 resampled += 80; 757 } 758 f.buf = strm->pcm_buf; 759 } else { 760 f.buf = strm->rec_buf; 761 } 762 763 /* Need to convert channel count? */ 764 if (strm->param.channel_count != 1) { 765 pjmedia_convert_channel_1ton((pj_int16_t*)f.buf, 766 (pj_int16_t*)f.buf, 767 strm->param.channel_count, 768 strm->param.samples_per_frame / 769 strm->param.channel_count, 770 0); 771 } 772 773 /* Call parent callback */ 719 774 f.type = PJMEDIA_FRAME_TYPE_AUDIO; 720 f.buf = strm->rec_buf; 721 f.size = strm->rec_buf_len << 1; 722 775 f.size = strm->param.samples_per_frame << 1; 723 776 strm->rec_cb(strm->user_data, &f); 724 777 strm->rec_buf_len = 0; … … 746 799 * encode the PCM samples into G.711 and put it into APS buffer. 747 800 */ 748 unsigned enc_len = 0; 749 while (enc_len < g711_frame_len) { 801 unsigned samples_processed = 0; 802 803 while (samples_processed < g711_frame_len) { 804 /* Need more samples to play, time to call parent callback */ 750 805 if (strm->play_buf_len == 0) { 751 806 pjmedia_frame f; 752 753 f.buf = strm->play_buf;807 unsigned samples_got; 808 754 809 f.size = strm->param.samples_per_frame << 1; 755 810 if (strm->play_resample || strm->param.channel_count != 1) 811 f.buf = strm->pcm_buf; 812 else 813 f.buf = strm->play_buf; 814 815 /* Call parent callback */ 756 816 strm->play_cb(strm->user_data, &f); 757 817 if (f.type != PJMEDIA_FRAME_TYPE_AUDIO) { 758 pjmedia_zero_samples( strm->play_buf,818 pjmedia_zero_samples((pj_int16_t*)f.buf, 759 819 strm->param.samples_per_frame); 760 820 } 761 821 762 strm->play_buf_len = strm->param.samples_per_frame; 822 samples_got = strm->param.samples_per_frame / 823 strm->param.channel_count / 824 strm->resample_factor; 825 826 /* Need to convert channel count? */ 827 if (strm->param.channel_count != 1) { 828 pjmedia_convert_channel_nto1((pj_int16_t*)f.buf, 829 (pj_int16_t*)f.buf, 830 strm->param.channel_count, 831 strm->param.samples_per_frame, 832 PJ_FALSE, 833 0); 834 } 835 836 /* Need to resample clock rate? */ 837 if (strm->play_resample) { 838 unsigned resampled = 0; 839 840 while (resampled < samples_got) 841 { 842 pjmedia_resample_run(strm->play_resample, 843 strm->pcm_buf + 844 resampled * strm->resample_factor, 845 &strm->play_buf[resampled]); 846 resampled += 80; 847 } 848 } 849 850 strm->play_buf_len = samples_got; 763 851 strm->play_buf_start = 0; 764 852 } … … 766 854 unsigned tmp; 767 855 768 tmp = PJ_MIN(strm->play_buf_len, g711_frame_len - enc_len);856 tmp = PJ_MIN(strm->play_buf_len, g711_frame_len - samples_processed); 769 857 pjmedia_ulaw_encode((pj_uint8_t*)&strm->play_buf[strm->play_buf_start], 770 858 &strm->play_buf[strm->play_buf_start], 771 859 tmp); 772 860 buf.iBuffer.Append((TUint8*)&strm->play_buf[strm->play_buf_start], tmp); 773 enc_len+= tmp;861 samples_processed += tmp; 774 862 strm->play_buf_len -= tmp; 775 863 strm->play_buf_start += tmp; … … 778 866 779 867 /**************************************************************************** 780 * Internal APS callbacks 868 * Internal APS callbacks for non-PCM format 781 869 */ 782 870 … … 1263 1351 PJ_ASSERT_RETURN(param->bits_per_sample == BITS_PER_SAMPLE, PJ_EINVAL); 1264 1352 1353 /* Supported clock rates: 1354 * - for non-PCM format: 8kHz 1355 * - for PCM format: 8kHz and 16kHz 1356 */ 1357 PJ_ASSERT_RETURN(param->clock_rate == 8000 || 1358 (param->clock_rate == 16000 && 1359 param->ext_fmt.id == PJMEDIA_FORMAT_L16), 1360 PJ_EINVAL); 1361 1362 /* Supported channels number: 1363 * - for non-PCM format: mono 1364 * - for PCM format: mono and stereo 1365 */ 1366 PJ_ASSERT_RETURN(param->channel_count == 1 || 1367 (param->channel_count == 2 && 1368 param->ext_fmt.id == PJMEDIA_FORMAT_L16), 1369 PJ_EINVAL); 1370 1265 1371 /* Create and Initialize stream descriptor */ 1266 1372 pool = pj_pool_create(af->pf, "aps-dev", 1000, 1000, NULL); … … 1342 1448 } 1343 1449 1450 strm->rec_cb = rec_cb; 1451 strm->play_cb = play_cb; 1452 strm->user_data = user_data; 1453 strm->resample_factor = strm->param.clock_rate / 8000; 1454 1455 /* play_buf size is samples per frame scaled in to 8kHz mono. */ 1456 strm->play_buf = (pj_int16_t*)pj_pool_zalloc( 1457 pool, 1458 (strm->param.samples_per_frame / 1459 strm->resample_factor / 1460 strm->param.channel_count) << 1); 1461 strm->play_buf_len = 0; 1462 strm->play_buf_start = 0; 1463 1464 /* rec_buf size is samples per frame scaled in to 8kHz mono. */ 1465 strm->rec_buf = (pj_int16_t*)pj_pool_zalloc( 1466 pool, 1467 (strm->param.samples_per_frame / 1468 strm->resample_factor / 1469 strm->param.channel_count) << 1); 1470 strm->rec_buf_len = 0; 1471 1472 if (strm->param.ext_fmt.id == PJMEDIA_FORMAT_G729) { 1473 TBitStream *g729_bitstream = new TBitStream; 1474 1475 PJ_ASSERT_RETURN(g729_bitstream, PJ_ENOMEM); 1476 strm->strm_data = (void*)g729_bitstream; 1477 } 1478 1479 /* Init resampler when format is PCM and clock rate is not 8kHz */ 1480 if (strm->param.clock_rate != 8000 && 1481 strm->param.ext_fmt.id == PJMEDIA_FORMAT_L16) 1482 { 1483 pj_status_t status; 1484 1485 if (strm->param.dir & PJMEDIA_DIR_CAPTURE) { 1486 /* Create resample for recorder */ 1487 status = pjmedia_resample_create( pool, PJ_TRUE, PJ_FALSE, 1, 1488 8000, 1489 strm->param.clock_rate, 1490 80, 1491 &strm->rec_resample); 1492 if (status != PJ_SUCCESS) 1493 return status; 1494 } 1495 1496 if (strm->param.dir & PJMEDIA_DIR_PLAYBACK) { 1497 /* Create resample for player */ 1498 status = pjmedia_resample_create( pool, PJ_TRUE, PJ_FALSE, 1, 1499 strm->param.clock_rate, 1500 8000, 1501 80 * strm->resample_factor, 1502 &strm->play_resample); 1503 if (status != PJ_SUCCESS) 1504 return status; 1505 } 1506 } 1507 1508 /* Create PCM buffer, when the clock rate is not 8kHz or not mono */ 1509 if (strm->param.ext_fmt.id == PJMEDIA_FORMAT_L16 && 1510 (strm->resample_factor > 1 || strm->param.channel_count != 1)) 1511 { 1512 strm->pcm_buf = (pj_int16_t*)pj_pool_zalloc(pool, 1513 strm->param.samples_per_frame << 1); 1514 } 1515 1516 1344 1517 /* Create the audio engine. */ 1345 1518 TRAPD(err, strm->engine = CPjAudioEngine::NewL(strm, … … 1357 1530 } 1358 1531 1359 strm->rec_cb = rec_cb;1360 strm->play_cb = play_cb;1361 strm->user_data = user_data;1362 1363 /* play_buf size is samples per frame. */1364 strm->play_buf = (pj_int16_t*)pj_pool_zalloc(pool,1365 strm->param.samples_per_frame << 1);1366 strm->play_buf_len = 0;1367 strm->play_buf_start = 0;1368 1369 /* rec_buf size is samples per frame. */1370 strm->rec_buf = (pj_int16_t*)pj_pool_zalloc(pool,1371 strm->param.samples_per_frame << 1);1372 strm->rec_buf_len = 0;1373 1374 if (strm->param.ext_fmt.id == PJMEDIA_FORMAT_G729) {1375 TBitStream *g729_bitstream = new TBitStream;1376 1377 PJ_ASSERT_RETURN(g729_bitstream, PJ_ENOMEM);1378 strm->strm_data = (void*)g729_bitstream;1379 }1380 1381 1532 /* Done */ 1382 1533 strm->base.op = &stream_op; -
pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_mda_dev.cpp
r2668 r2677 271 271 lastError_(KErrNone), timeStamp_(0), 272 272 frameLen_(parent_strm->param.samples_per_frame * 273 parent_strm->param.channel_count *274 273 BYTES_PER_SAMPLE), 275 274 frameRecBuf_(NULL), frameRecBufLen_(0) … … 426 425 } 427 426 428 if (frameRecBufLen_ || aBuffer. Size() < frameLen_) {429 pj_memcpy(frameRecBuf_ + frameRecBufLen_, (void*) aBuffer.Ptr(), aBuffer. Size());430 frameRecBufLen_ += aBuffer. Size();427 if (frameRecBufLen_ || aBuffer.Length() < frameLen_) { 428 pj_memcpy(frameRecBuf_ + frameRecBufLen_, (void*) aBuffer.Ptr(), aBuffer.Length()); 429 frameRecBufLen_ += aBuffer.Length(); 431 430 } 432 431 … … 454 453 f.type = PJMEDIA_FRAME_TYPE_AUDIO; 455 454 f.buf = (void*)aBuffer.Ptr(); 456 f.size = aBuffer. Size();455 f.size = aBuffer.Length(); 457 456 f.timestamp.u32.lo = timeStamp_; 458 457 f.bit_info = 0; … … 572 571 { 573 572 frameBufSize_ = parentStrm_->param.samples_per_frame * 574 parentStrm_->param.channel_count *575 573 BYTES_PER_SAMPLE; 576 574 frameBuf_ = new TUint8[frameBufSize_]; … … 898 896 param->ext_fmt.id == PJMEDIA_FORMAT_L16, 899 897 PJ_ENOTSUP); 898 899 /* It seems that MDA recorder only supports for mono channel. */ 900 PJ_ASSERT_RETURN(param->channel_count == 1, PJ_EINVAL); 900 901 901 902 /* Create and Initialize stream descriptor */
Note: See TracChangeset
for help on using the changeset viewer.