|
Posted on 2009-12-07 16:24 jacky_zz 阅读(1769) 评论(8) 编辑 收藏 引用
在Windows XP上安装VMware6.5,下载最新的Ubuntu 9.10桌面版安装到虚拟机上。系统安装完成后,设置网络,从 http://ffmpeg.org上下载最新的源码版本,以root身份解压到根目录上,得到目录ffmpeg-0.5,运行以下命令: #cd ffmpeg-0.5 #./configure --prefix=/usr --enable-shared --disable-static --enable-memalign-hack #make #make install #make distclean(可选) 完成编译和安装后,开始编码,代码如下:
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 14typedef 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 36int audio_decode_frame(AudioState* pState); 37int read_buffer(AudioState* pState, void* buffer, int buf_size); 38 39int 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 198int 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 241int 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}
或者点击此处 下载源码文件。 编译程序,运行命令: #gcc ffmpeg_player.c -o ffmpeg_player -lavcodec -lavformat -lavutil 或者 #gcc -DOUTPUT_INFORMATS ffmpeg_player.c -o ffmpeg_player -lavcodec -lavformat -lavutil 编译完成后,运行如下命令即可播放音乐文件了 #./ffmpeg_player /music/1.ape ENJOY!
Feedback
# re: ffmpeg_play on ubuntu 9.10 回复 更多评论
2009-12-08 13:08 by
不错,如果有个gtk或qt的图形界面就更好了。
有时间能做一个 基于DirectShow 来做的频谱分析示例来吗,谢谢,820156394@qq.com
# re: ffmpeg_play on ubuntu 9.10 回复 更多评论
2009-12-14 15:09 by
你提到的这个问题,在codeproject有例子的,无非需要做的自己开发一个Filter,并注册到系统,以便系统能以你开发的Filter来解码输入的文件,并将解码数据返回给应用程序进行播放。
例子的地址为: http://www.codeproject.com/KB/audio-video/PeakMeterCS.aspx
# re: ffmpeg_play on ubuntu 9.10 回复 更多评论
2009-12-14 16:06 by
@jacky_zz
我都无语了,太感谢了,没想到你给我回复的那么快
为了你的那个频谱分析,我把我的DirectShow 项目变成了DirectSound的,然后几乎全部的功能差不多都改好了,就差一个:滑动滚动条来控制歌曲播放位置
因为文件有MP3,wma,然后我试图更改m_bytePosition出错,还正在细看你的代码,不知如何来做
# re: ffmpeg_play on ubuntu 9.10 回复 更多评论
2009-12-14 22:26 by
你好,我现在都不想自己去写具体格式的音频解码代码了,我想采用ffmpeg作为解码后台,这样做有几个好处:一是可以把程序开发的重点从解码转移到程序架构的设计上来;二是ffmpeg支持的格式也比较多,这样一来程序就可以播放多种格式的音频文件了,我现在测试了aac,ape,flac,mp3,mp4,mpc,ogg,wma,wav,效果还不错;三是编写几个封装DLL,用于ffmpeg和DirectSound操作的封装,这样就越发模块化了。呵呵,这个只是我的一个初步的想法,等封装完成,那么剩下的工作就是界面编程了,有兴趣的话,一起来整整?
PS:最近几天准备用VC6来开发程序,在多个系统上测试,包括Ubuntu(9.10,Wine v1.01)。
我的QQ是:59502553。
# re: ffmpeg_play on ubuntu 9.10 回复 更多评论
2009-12-18 10:57 by
# re: ffmpeg_play on ubuntu 9.10 回复 更多评论
2009-12-18 10:59 by
482. jacky_zz (rss) (7,12-08 09:37,5908) ,你排名靠后了,加油呀,
# re: ffmpeg_play on ubuntu 9.10 回复 更多评论
2010-04-12 13:44 by
不错,学习下,支持你一个
|