00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <string.h>
00021 #include <stdlib.h>
00022 #include "OStreamAudioEncoder.hh"
00023
00024
00025 OStreamAudioEncoder::OStreamAudioEncoder( unsigned int io_buf_size, ostream_encoding_type encoding_type,
00026 int num_channels ) :
00027 _internal_buffer_size( io_buf_size ),
00028 _encoding_type( encoding_type ),
00029 _num_channels( num_channels )
00030 {
00031 _initialized = false;
00032 if ( io_buf_size <= 1 ) {
00033 DEBUG_PRINT ("io_buf_size is wrong\n.");
00034 return;
00035 }
00036
00037
00038 _internal_buffer = new unsigned char[_internal_buffer_size];
00039
00040 _ready_to_encode_frame = NULL;
00041 if ( encoder_initialize () == true ) {
00042 _initialized = true;
00043 }
00044 }
00045
00046 OStreamAudioEncoder::~OStreamAudioEncoder ()
00047 {
00048 if ( _internal_buffer )
00049 delete _internal_buffer;
00050
00051 if ( _ready_to_encode_frame )
00052 free( _ready_to_encode_frame );
00053
00054 free_pcm_buffer ();
00055 av_close_input_file( _out_fmt_context );
00056
00057
00058
00059
00060
00061 }
00062
00063
00064
00065 bool OStreamAudioEncoder::open_codec( AVStream *stream )
00066 {
00067 AVCodec *codec;
00068 AVCodecContext *codec_context;
00069
00070 codec_context = stream->codec;
00071
00072
00073 codec = avcodec_find_encoder( codec_context->codec_id );
00074 if ( !codec ) {
00075 DEBUG_PRINT ("codec not found\n");
00076 return false;
00077 }
00078
00079
00080 if ( avcodec_open( codec_context, codec ) < 0 ) {
00081 return false;
00082 }
00083
00084 return true;
00085 }
00086
00087
00088 AVStream* OStreamAudioEncoder::create_audio_stream( AVFormatContext *io_fmt_context, int codec_id )
00089 {
00090 AVCodecContext *codec_context;
00091 AVStream *stream;
00092
00093
00094
00095
00096 stream = av_new_stream( io_fmt_context, 0 );
00097 if ( !stream ) {
00098 DEBUG_PRINT ("Could not alloc stream\n");
00099 return NULL;
00100 }
00101
00102
00103
00104 codec_context = stream->codec;
00105 codec_context->codec_id = (CodecID)codec_id;
00106 codec_context->codec_type = CODEC_TYPE_AUDIO;
00107
00108 codec_context->bit_rate = 64000;
00109 codec_context->sample_rate = 44100;
00110 codec_context->channels = _num_channels;
00111
00112 return stream;
00113 }
00114
00115 bool OStreamAudioEncoder::encoder_initialize ()
00116 {
00117 char *encoding_str;
00118
00119 av_register_all();
00120
00121
00122
00123 if ( init_pcm_buffer( 2 * MAX_AUDIO_PACKET_SIZE ) == false )
00124 return false;
00125
00126
00127 switch ( _encoding_type ) {
00128 case OSTREAM_ENCODING_MP3:
00129 encoding_str = "mp3";
00130 _out_fmt = guess_format ( encoding_str, NULL, NULL);
00131
00132 if( !_out_fmt ) {
00133 DEBUG_PRINT( "Could not find suitable output format.\n");
00134 return false;
00135 }
00136 break;
00137
00138 default:
00139 DEBUG_PRINT ("could not find known OSTREAM_ENCODING type.\n" );
00140 break;
00141 }
00142
00143 _out_fmt_context = av_alloc_format_context ();
00144 if( !_out_fmt_context ) {
00145 DEBUG_PRINT( "Memory error.\n" );
00146 return false;
00147 }
00148
00149
00150 _out_fmt_context->oformat = _out_fmt;
00151
00152
00153 if ( _out_fmt->audio_codec == CODEC_ID_NONE ) {
00154 DEBUG_PRINT( "CODEC_ID_NONE\n" );
00155 return false;
00156 }
00157
00158
00159 if(!( _audio_stream = create_audio_stream( _out_fmt_context, _out_fmt->audio_codec ) )) {
00160 DEBUG_PRINT( "error in adding stream\n" );
00161 return false;
00162 }
00163
00164
00165 if ( av_set_parameters( _out_fmt_context, NULL ) < 0 ) {
00166 DEBUG_PRINT( "Invalid output format parameters\n" );
00167 return false;
00168 }
00169
00170
00171 if ( !open_codec( _audio_stream ) ) {
00172 DEBUG_PRINT( "could not open codec\n" );
00173 return false;
00174 }
00175
00176
00177 _frame_size = _audio_stream->codec->frame_size;
00178
00179
00180 _encoded_frame_size = _frame_size * 2 * _num_channels;
00181 _ready_to_encode_frame = (unsigned char*) calloc( _encoded_frame_size, sizeof(unsigned char) );
00182
00183 return true;
00184 }
00185
00186 const unsigned char* OStreamAudioEncoder::encode_audio_frame( unsigned char* in_pcm_buffer,
00187 int in_pcm_buffer_size, int *out_size )
00188 {
00189 AVCodecContext *codec_context;
00190
00191 *out_size = 0;
00192
00193 if ( in_pcm_buffer == NULL )
00194 return NULL;
00195
00196 if ( !_initialized ) {
00197 DEBUG_PRINT( "initializing class failed.\n" );
00198 return NULL;
00199 }
00200
00201
00202
00203
00204 write_pcm_buffer ( in_pcm_buffer, in_pcm_buffer_size );
00205
00206 if ( _ready_to_encode_frame == NULL ) {
00207 DEBUG_PRINT( "_ready_to_encode_frame == NULL\n");
00208 return NULL;
00209 }
00210
00211
00212 read_pcm_buffer( _ready_to_encode_frame, _encoded_frame_size );
00213
00214 if( in_pcm_buffer_size > _internal_buffer_size ) {
00215 DEBUG_PRINT( "in_buffer_size too big\n" );
00216 return NULL;
00217 }
00218
00219 codec_context = _audio_stream->codec;
00220
00221 *out_size = avcodec_encode_audio( codec_context, _internal_buffer, in_pcm_buffer_size, (short*)_ready_to_encode_frame );
00222
00223 return _internal_buffer;
00224 }
00225
00226
00227
00228 bool OStreamAudioEncoder::init_pcm_buffer ( int size )
00229 {
00230 _pcm_internal_buffer = (unsigned char*)calloc( size, sizeof(unsigned char) );
00231
00232 if (!_pcm_internal_buffer)
00233 return false;
00234
00235 _pcm_end_ptr = _pcm_internal_buffer + size;
00236 _pcm_write_ptr = _pcm_read_ptr = _pcm_internal_buffer;
00237
00238 return true;
00239 }
00240
00241 void OStreamAudioEncoder::free_pcm_buffer ()
00242 {
00243 if ( _pcm_internal_buffer != NULL )
00244 free( _pcm_internal_buffer );
00245 }
00246
00247 int OStreamAudioEncoder::read_pcm_buffer( unsigned char *buf, int buf_size )
00248 {
00249 int len;
00250 int size = _pcm_write_ptr - _pcm_read_ptr;
00251 if (size < 0)
00252 size += _pcm_end_ptr - _pcm_internal_buffer;
00253
00254 if (size < buf_size)
00255 return -1;
00256
00257 while (buf_size > 0) {
00258 len = ( _pcm_end_ptr - _pcm_read_ptr ) > ( buf_size ) ?
00259 ( buf_size ) : ( _pcm_end_ptr - _pcm_read_ptr );
00260
00261 memcpy( buf, _pcm_read_ptr, len );
00262 buf += len;
00263 _pcm_read_ptr += len;
00264
00265 if ( _pcm_read_ptr >= _pcm_end_ptr )
00266 _pcm_read_ptr = _pcm_internal_buffer;
00267
00268 buf_size -= len;
00269 }
00270
00271 return 0;
00272 }
00273
00274
00275 void OStreamAudioEncoder::write_pcm_buffer( const unsigned char *buf, int size )
00276 {
00277 int len;
00278
00279 while (size > 0) {
00280 len = ( _pcm_end_ptr - _pcm_write_ptr ) > ( size ) ?
00281 ( size ) : ( _pcm_end_ptr - _pcm_write_ptr );
00282
00283 memcpy( _pcm_write_ptr, buf, len );
00284 _pcm_write_ptr += len;
00285
00286 if ( _pcm_write_ptr >= _pcm_end_ptr )
00287 _pcm_write_ptr = _pcm_internal_buffer;
00288 buf += len;
00289 size -= len;
00290 }
00291 }
00292