Changeset 1983 for pjproject/trunk/pjmedia/src/pjmedia-codec/speex_codec.c
- Timestamp:
- Jun 5, 2008 10:50:40 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia-codec/speex_codec.c
r1965 r1983 161 161 return PJMEDIA_CODEC_EFAILED; 162 162 163 /* Set thequality */164 if (p->quality != -1)165 speex_encoder_ctl(state, SPEEX_SET_QUALITY, &p->quality);163 /* We have to get maximum bitrate, so let's set maximum quality */ 164 tmp = 10; 165 speex_encoder_ctl(state, SPEEX_SET_QUALITY, &tmp); 166 166 167 167 /* Sampling rate. */ … … 596 596 id = spx->param_id; 597 597 598 /* Only supports one frame per packet */599 PJ_ASSERT_RETURN(attr->setting.frm_per_pkt==1, PJ_EINVAL);600 601 598 /* 602 599 * Create and initialize encoder. … … 688 685 spx = (struct spx_private*) codec->codec_data; 689 686 690 /* Only supports one frame per packet */691 PJ_ASSERT_RETURN(attr->setting.frm_per_pkt==1, PJ_EINVAL);692 693 687 /* VAD */ 694 688 tmp = (attr->setting.vad != 0); … … 701 695 702 696 return PJ_SUCCESS; 697 } 698 699 #if 0 700 # define TRACE__(args) PJ_LOG(5,args) 701 #else 702 # define TRACE__(args) 703 #endif 704 705 #undef THIS_FUNC 706 #define THIS_FUNC "speex_get_next_frame" 707 708 #define NB_SUBMODES 16 709 #define NB_SUBMODE_BITS 4 710 711 #define SB_SUBMODES 8 712 #define SB_SUBMODE_BITS 3 713 714 /* This function will iterate frames & submodes in the Speex bits. 715 * Returns 0 if a frame found, otherwise returns -1. 716 */ 717 int speex_get_next_frame(SpeexBits *bits) 718 { 719 static const int inband_skip_table[NB_SUBMODES] = 720 {1, 1, 4, 4, 4, 4, 4, 4, 8, 8, 16, 16, 32, 32, 64, 64 }; 721 static const int wb_skip_table[SB_SUBMODES] = 722 {SB_SUBMODE_BITS+1, 36, 112, 192, 352, -1, -1, -1}; 723 724 unsigned submode; 725 unsigned nb_count = 0; 726 727 while (speex_bits_remaining(bits) >= 5) { 728 unsigned wb_count = 0; 729 unsigned bit_ptr = bits->bitPtr; 730 unsigned char_ptr = bits->charPtr; 731 732 /* WB frame */ 733 while ((speex_bits_remaining(bits) >= 4) 734 && speex_bits_unpack_unsigned(bits, 1)) 735 { 736 int advance; 737 738 submode = speex_bits_unpack_unsigned(bits, 3); 739 advance = wb_skip_table[submode]; 740 if (advance < 0) { 741 TRACE__((THIS_FUNC, "Invalid mode encountered. " 742 "The stream is corrupted.")); 743 return -1; 744 } 745 TRACE__((THIS_FUNC, "WB layer skipped: %d bits", advance)); 746 advance -= (SB_SUBMODE_BITS+1); 747 speex_bits_advance(bits, advance); 748 749 bit_ptr = bits->bitPtr; 750 char_ptr = bits->charPtr; 751 752 /* Consecutive subband frames may not exceed 2 frames */ 753 if (++wb_count > 2) 754 return -1; 755 } 756 757 /* End of bits, return the frame */ 758 if (speex_bits_remaining(bits) < 4) { 759 TRACE__((THIS_FUNC, "End of stream")); 760 return 0; 761 } 762 763 /* Stop iteration, return the frame */ 764 if (nb_count > 0) { 765 bits->bitPtr = bit_ptr; 766 bits->charPtr = char_ptr; 767 return 0; 768 } 769 770 /* Get control bits */ 771 submode = speex_bits_unpack_unsigned(bits, 4); 772 TRACE__((THIS_FUNC, "Control bits: %d at %d", 773 submode, bits->charPtr*8+bits->bitPtr)); 774 775 if (submode == 15) { 776 TRACE__((THIS_FUNC, "Found submode: terminator")); 777 return 0; 778 } else if (submode == 14) { 779 /* in-band signal; next 4 bits contain signal id */ 780 submode = speex_bits_unpack_unsigned(bits, 4); 781 TRACE__((THIS_FUNC, "Found submode: in-band %d bits", 782 inband_skip_table[submode])); 783 speex_bits_advance(bits, inband_skip_table[submode]); 784 } else if (submode == 13) { 785 /* user in-band; next 5 bits contain msg len */ 786 submode = speex_bits_unpack_unsigned(bits, 5); 787 TRACE__((THIS_FUNC, "Found submode: user-band %d bytes", submode)); 788 speex_bits_advance(bits, submode * 8); 789 } else if (submode > 8) { 790 TRACE__((THIS_FUNC, "Unknown sub-mode %d", submode)); 791 return 0; 792 } else { 793 /* NB frame */ 794 unsigned int advance = submode; 795 speex_mode_query(&speex_nb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance); 796 if (advance < 0) { 797 TRACE__((THIS_FUNC, "Invalid mode encountered. " 798 "The stream is corrupted.")); 799 return -1; 800 } 801 TRACE__((THIS_FUNC, "Submode %d: %d bits", submode, advance)); 802 advance -= (NB_SUBMODE_BITS+1); 803 speex_bits_advance(bits, advance); 804 805 ++nb_count; 806 } 807 } 808 809 return 0; 703 810 } 704 811 … … 714 821 pjmedia_frame frames[]) 715 822 { 716 struct spx_private *spx; 717 unsigned frame_size, samples_per_frame; 718 unsigned count; 719 720 spx = (struct spx_private*) codec->codec_data; 721 722 frame_size = spx_factory.speex_param[spx->param_id].framesize; 723 samples_per_frame = spx_factory.speex_param[spx->param_id].samples_per_frame; 724 725 /* Don't really know how to do this... */ 726 count = 0; 727 while (pkt_size >= frame_size && count < *frame_cnt) { 728 frames[count].buf = pkt; 729 frames[count].size = frame_size; 823 struct spx_private *spx = (struct spx_private*) codec->codec_data; 824 unsigned samples_per_frame; 825 unsigned count = 0; 826 int char_ptr = 0; 827 int bit_ptr = 0; 828 829 samples_per_frame=spx_factory.speex_param[spx->param_id].samples_per_frame; 830 831 /* Copy the data into the speex bit-stream */ 832 speex_bits_read_from(&spx->dec_bits, (char*)pkt, pkt_size); 833 834 while (speex_get_next_frame(&spx->dec_bits) == 0 && 835 spx->dec_bits.charPtr != char_ptr) 836 { 837 frames[count].buf = (char*)pkt + char_ptr; 838 /* Bit info contains start bit offset of the frame */ 839 frames[count].bit_info = bit_ptr; 730 840 frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO; 731 841 frames[count].timestamp.u64 = ts->u64 + count * samples_per_frame; 732 733 pkt_size -= frame_size; 842 frames[count].size = spx->dec_bits.charPtr - char_ptr; 843 if (spx->dec_bits.bitPtr) 844 ++frames[count].size; 845 846 bit_ptr = spx->dec_bits.bitPtr; 847 char_ptr = spx->dec_bits.charPtr; 848 734 849 ++count; 735 pkt = ((char*)pkt) + frame_size;736 }737 738 /* Just in case speex has silence frame which size is less than normal739 * frame size...740 */741 if (pkt_size && count < *frame_cnt) {742 frames[count].buf = pkt;743 frames[count].size = pkt_size;744 frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;745 frames[count].timestamp.u64 = ts->u64 + count * samples_per_frame;746 ++count;747 850 } 748 851 749 852 *frame_cnt = count; 750 return PJ_SUCCESS; 751 } 752 753 /* 754 * Encode frame. 853 854 return PJ_SUCCESS; 855 } 856 857 /* 858 * Encode frames. 755 859 */ 756 860 static pj_status_t spx_codec_encode( pjmedia_codec *codec, … … 760 864 { 761 865 struct spx_private *spx; 762 unsigned sz; 763 int tx; 866 unsigned samples_per_frame; 867 int tx = 0; 868 spx_int16_t *pcm_in = (spx_int16_t*)input->buf; 869 unsigned nsamples; 764 870 765 871 spx = (struct spx_private*) codec->codec_data; … … 773 879 } 774 880 881 nsamples = input->size >> 1; 882 samples_per_frame=spx_factory.speex_param[spx->param_id].samples_per_frame; 883 884 PJ_ASSERT_RETURN(nsamples % samples_per_frame == 0, 885 PJMEDIA_CODEC_EPCMFRMINLEN); 886 775 887 /* Flush all the bits in the struct so we can encode a new frame */ 776 888 speex_bits_reset(&spx->enc_bits); 777 889 778 /* Encode the frame */ 779 tx = speex_encode_int(spx->enc, (spx_int16_t*)input->buf, 780 &spx->enc_bits); 890 /* Encode the frames */ 891 while (nsamples >= samples_per_frame) { 892 tx += speex_encode_int(spx->enc, pcm_in, &spx->enc_bits); 893 pcm_in += samples_per_frame; 894 nsamples -= samples_per_frame; 895 } 781 896 782 897 /* Check if we need not to transmit the frame (DTX) */ … … 790 905 791 906 /* Check size. */ 792 sz = speex_bits_nbytes(&spx->enc_bits); 793 pj_assert(sz <= output_buf_len); 907 pj_assert(speex_bits_nbytes(&spx->enc_bits) <= (int)output_buf_len); 794 908 795 909 /* Copy the bits to an array of char that can be written */ … … 811 925 { 812 926 struct spx_private *spx; 927 unsigned samples_per_frame; 813 928 814 929 spx = (struct spx_private*) codec->codec_data; 815 816 PJ_ASSERT_RETURN(output_buf_len >= 320, PJMEDIA_CODEC_EPCMTOOSHORT); 930 samples_per_frame=spx_factory.speex_param[spx->param_id].samples_per_frame; 931 932 PJ_ASSERT_RETURN(output_buf_len >= samples_per_frame << 1, 933 PJMEDIA_CODEC_EPCMTOOSHORT); 817 934 818 935 if (input->type != PJMEDIA_FRAME_TYPE_AUDIO) { 819 pjmedia_zero_samples((pj_int16_t*)output->buf, 160);820 output->size = 320;936 pjmedia_zero_samples((pj_int16_t*)output->buf, samples_per_frame); 937 output->size = samples_per_frame << 1; 821 938 output->timestamp.u64 = input->timestamp.u64; 822 939 output->type = PJMEDIA_FRAME_TYPE_AUDIO; … … 826 943 /* Copy the data into the bit-stream struct */ 827 944 speex_bits_read_from(&spx->dec_bits, (char*)input->buf, input->size); 945 946 /* Set Speex dec_bits pointer to the start bit of the frame */ 947 speex_bits_advance(&spx->dec_bits, input->bit_info); 828 948 829 949 /* Decode the data */ … … 831 951 832 952 output->type = PJMEDIA_FRAME_TYPE_AUDIO; 833 output->size = 320;953 output->size = samples_per_frame << 1; 834 954 output->timestamp.u64 = input->timestamp.u64; 835 836 955 837 956 return PJ_SUCCESS;
Note: See TracChangeset
for help on using the changeset viewer.