|
Posted on 2009-12-07 16:24 jacky_zz 閱讀(1793) 評(píng)論(8) 編輯 收藏 引用
在Windows XP上安裝VMware6.5,下載最新的Ubuntu 9.10桌面版安裝到虛擬機(jī)上。系統(tǒng)安裝完成后,設(shè)置網(wǎng)絡(luò),從 http://ffmpeg.org上下載最新的源碼版本,以root身份解壓到根目錄上,得到目錄ffmpeg-0.5,運(yùn)行以下命令: #cd ffmpeg-0.5 #./configure --prefix=/usr --enable-shared --disable-static --enable-memalign-hack #make #make install #make distclean(可選) 完成編譯和安裝后,開(kāi)始編碼,代碼如下:
1 #include <unistd.h> 2 #include <fcntl.h> 3 #include <sys/types.h> 4 #include <sys/ioctl.h> 5 #include <linux/soundcard.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <libavcodec/avcodec.h> 9 #include <libavformat/avformat.h> 10 #include <libavutil/mem.h> 11 12 #define BLOCK_SIZE 4608 13 14 typedef struct AudioState 15  { 16 AVFormatContext* pFmtCtx; 17 AVCodecContext* pCodecCtx; 18 AVCodec* pCodec; 19 20 #ifdef OUTPUT_INFORMATS 21 AVInputFormat* ifmt; 22 #endif 23 24 uint8_t* audio_buf1; 25 uint8_t* audio_buf; 26 unsigned int audio_buf_size; 27 unsigned int buffer_size; 28 int audio_buf_index; 29 AVPacket audio_pkt_temp; 30 AVPacket audio_pkt; 31 uint8_t* audio_pkt_data; 32 int audio_pkt_size; 33 int stream_index; 34 } AudioState; 35 36 int audio_decode_frame(AudioState* pState); 37 int read_buffer(AudioState* pState, void* buffer, int buf_size); 38 39 int main(int argc, char* argv[]) 40  { 41 int err = 0; 42 int handle = 0; 43 int i = 0; 44 int status = 0; 45 int args = 0; 46 int index = 0; 47 int sample_rate = 0, bits_per_sample = 0, channels = 0; 48 int done = 0; 49 char buffer[BLOCK_SIZE] = {0}; 50 AudioState state; 51 int buffer_size = (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2; 52 53 if(argc == 1) 54 { 55 printf("%s <filename>\n", argv[0]); 56 return 0; 57 } 58 59 // register all codecs. 60 av_register_all(); 61 memset(&state, 0, sizeof(AudioState)); 62 state.audio_buf1= (uint8_t*)av_mallocz(buffer_size); 63 state.buffer_size = buffer_size; 64 65 #ifdef OUTPUT_INFORMATS 66 state.ifmt = av_iformat_next(NULL); 67 for( ; ; ) 68 { 69 if(!state.ifmt) 70 break; 71 72 printf("%s [%s] [%s]\n", state.ifmt->name, state.ifmt->long_name, 73 state.ifmt->extensions); 74 state.ifmt = av_iformat_next(state.ifmt); 75 } 76 #endif 77 78 err = av_open_input_file(&state.pFmtCtx, argv[1], NULL, 0, NULL); 79 if(err < 0) 80 { 81 printf("can not open file %s.\n", argv[1]); 82 return 0; 83 } 84 85 err = av_find_stream_info(state.pFmtCtx); 86 if(err < 0) 87 { 88 printf("can not find stream info of file %s.\n", argv[1]); 89 return 0; 90 } 91 92 for(i = 0; i < state.pFmtCtx->nb_streams; i++) 93 { 94 if(state.pFmtCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) 95 { 96 state.pCodecCtx = state.pFmtCtx->streams[i]->codec; 97 index = i; 98 state.stream_index = i; 99 break; 100 } 101 } 102 103 if(!state.pCodecCtx) 104 { 105 printf("can not get codec context.\n"); 106 av_close_input_file(state.pFmtCtx); 107 108 return 0; 109 } 110 111 state.pCodec = avcodec_find_decoder(state.pCodecCtx->codec_id); 112 if(!state.pCodec || avcodec_open(state.pCodecCtx, state.pCodec) < 0) 113 { 114 printf("can not open codec.\n"); 115 av_close_input_file(state.pFmtCtx); 116 117 return 0; 118 } 119 120 sample_rate = state.pCodecCtx->sample_rate; 121 channels = state.pCodecCtx->channels; 122 switch(state.pCodecCtx->sample_fmt) 123 { 124 case SAMPLE_FMT_U8: 125 bits_per_sample = 8; 126 break; 127 case SAMPLE_FMT_S16: 128 bits_per_sample = 16; 129 break; 130 case SAMPLE_FMT_S32: 131 bits_per_sample = 32; 132 break; 133 default: 134 bits_per_sample = 16; 135 } 136 137 printf("sample_rate: %d Hz\n", sample_rate); 138 printf("channels: %d\n", channels); 139 printf("bits_per_sample: %d bit\n", bits_per_sample); 140 141 handle = open("/dev/dsp", O_RDWR); 142 if(handle < 0) 143 { 144 printf("can not open /dev/dsp.\n"); 145 return 0; 146 } 147 148 args = sample_rate; 149 status = ioctl(handle, SOUND_PCM_WRITE_RATE, &args); 150 if(status == -1) 151 { 152 printf("SOUND_PCM_WRITE_RATE ioctl failed.\n"); 153 return 0; 154 } 155 156 args = channels; 157 status = ioctl(handle, SOUND_PCM_WRITE_CHANNELS, &args); 158 if(status == -1) 159 { 160 printf("SOUND_PCM_WRITE_CHANNELS ioctl failed.\n"); 161 return 0; 162 } 163 164 args = bits_per_sample; 165 status = ioctl(handle, SOUND_PCM_WRITE_BITS, &args); 166 if(status == -1) 167 { 168 printf("SOUND_PCM_WRITE_BITS ioctl failed.\n"); 169 return 0; 170 } 171 172 for( ; ; ) 173 { 174 int len = BLOCK_SIZE; 175 int size = 0; 176 char* pbuffer = buffer; 177 if(done) 178 break; 179 180 size = read_buffer(&state, buffer, len); 181 if(size == -1) 182 { 183 done = 1; 184 continue; 185 } 186 187 // printf("size=%d\n", size); 188 write(handle, buffer, size); 189 } 190 191 avcodec_close(state.pCodecCtx); 192 av_close_input_file(state.pFmtCtx); 193 av_free(state.audio_buf1); 194 close(handle); 195 return 0; 196 } 197 198 int audio_decode_frame(AudioState* pState) 199  { 200 AVPacket* pkt_temp = &pState->audio_pkt_temp; 201 AVPacket* pkt = &pState->audio_pkt; 202 AVCodecContext* dec = pState->pCodecCtx; 203 int len = 0, data_size = 0; 204 int err = 0; 205 206 for( ; ; ) 207 { 208 while(pkt_temp->size > 0) 209 { 210 data_size = pState->buffer_size; 211 len = avcodec_decode_audio2(dec, (int16_t*)pState->audio_buf1, &data_size, pkt_temp->data, pkt_temp->size); 212 if(len < 0) 213 { 214 pkt_temp->size = 0; 215 break; 216 } 217 218 pkt_temp->data += len; 219 pkt_temp->size -= len; 220 221 if(data_size <= 0) 222 continue; 223 224 pState->audio_buf = pState->audio_buf1; 225 return data_size; 226 } 227 228 if(pkt->data) 229 av_free_packet(pkt); 230 231 if((err = av_read_frame(pState->pFmtCtx, pkt)) < 0) 232 return -1; 233 234 pkt_temp->data = pkt->data; 235 pkt_temp->size = pkt->size; 236 } 237 238 return -1; 239 } 240 241 int read_buffer(AudioState* pState, void* buffer, int buf_size) 242  { 243 int len = buf_size; 244 uint8_t* pbuffer = (uint8_t*)buffer; 245 int audio_size = 0; 246 int len1 = 0; 247 int size = 0; 248 249 while(len > 0) 250 { 251 if(pState->audio_buf_index >= pState->audio_buf_size) 252 { 253 audio_size = audio_decode_frame(pState); 254 if(audio_size < 0) 255 return (size > 0) ? size : -1; 256 257 pState->audio_buf_size = audio_size; 258 pState->audio_buf_index = 0; 259 } 260 261 len1 = pState->audio_buf_size - pState->audio_buf_index; 262 if(len1 > len) 263 len1 = len; 264 265 memcpy(pbuffer, (uint8_t*)pState->audio_buf + pState->audio_buf_index, len1); 266 267 len -= len1; 268 pbuffer += len1; 269 size += len1; 270 pState->audio_buf_index += len1; 271 } 272 273 return size; 274 }
或者點(diǎn)擊此處 下載源碼文件。 編譯程序,運(yùn)行命令: #gcc ffmpeg_player.c -o ffmpeg_player -lavcodec -lavformat -lavutil 或者 #gcc -DOUTPUT_INFORMATS ffmpeg_player.c -o ffmpeg_player -lavcodec -lavformat -lavutil 編譯完成后,運(yùn)行如下命令即可播放音樂(lè)文件了 #./ffmpeg_player /music/1.ape ENJOY!
Feedback
不錯(cuò),如果有個(gè)gtk或qt的圖形界面就更好了。
有時(shí)間能做一個(gè) 基于DirectShow 來(lái)做的頻譜分析示例來(lái)嗎,謝謝,820156394@qq.com
你提到的這個(gè)問(wèn)題,在codeproject有例子的,無(wú)非需要做的自己開(kāi)發(fā)一個(gè)Filter,并注冊(cè)到系統(tǒng),以便系統(tǒng)能以你開(kāi)發(fā)的Filter來(lái)解碼輸入的文件,并將解碼數(shù)據(jù)返回給應(yīng)用程序進(jìn)行播放。
例子的地址為: http://www.codeproject.com/KB/audio-video/PeakMeterCS.aspx
@jacky_zz
我都無(wú)語(yǔ)了,太感謝了,沒(méi)想到你給我回復(fù)的那么快
為了你的那個(gè)頻譜分析,我把我的DirectShow 項(xiàng)目變成了DirectSound的,然后幾乎全部的功能差不多都改好了,就差一個(gè):滑動(dòng)滾動(dòng)條來(lái)控制歌曲播放位置
因?yàn)槲募蠱P3,wma,然后我試圖更改m_bytePosition出錯(cuò),還正在細(xì)看你的代碼,不知如何來(lái)做
你好,我現(xiàn)在都不想自己去寫具體格式的音頻解碼代碼了,我想采用ffmpeg作為解碼后臺(tái),這樣做有幾個(gè)好處:一是可以把程序開(kāi)發(fā)的重點(diǎn)從解碼轉(zhuǎn)移到程序架構(gòu)的設(shè)計(jì)上來(lái);二是ffmpeg支持的格式也比較多,這樣一來(lái)程序就可以播放多種格式的音頻文件了,我現(xiàn)在測(cè)試了aac,ape,flac,mp3,mp4,mpc,ogg,wma,wav,效果還不錯(cuò);三是編寫幾個(gè)封裝DLL,用于ffmpeg和DirectSound操作的封裝,這樣就越發(fā)模塊化了。呵呵,這個(gè)只是我的一個(gè)初步的想法,等封裝完成,那么剩下的工作就是界面編程了,有興趣的話,一起來(lái)整整?
PS:最近幾天準(zhǔn)備用VC6來(lái)開(kāi)發(fā)程序,在多個(gè)系統(tǒng)上測(cè)試,包括Ubuntu(9.10,Wine v1.01)。
我的QQ是:59502553。
482. jacky_zz (rss) (7,12-08 09:37,5908) ,你排名靠后了,加油呀,
不錯(cuò),學(xué)習(xí)下,支持你一個(gè)
|