00001 #include "avcodec.h"
00002 #include "funcprotos.h"
00003 #include "quicktime.h"
00004 #include <string.h>
00005 #include "wma.h"
00006
00007
00008
00009
00010 typedef struct
00011 {
00012
00013 char *work_buffer;
00014
00015 int64_t output_position;
00016
00017 long output_size;
00018
00019 long output_allocated;
00020 char *packet_buffer;
00021 int packet_allocated;
00022
00023 int64_t chunk;
00024
00025
00026
00027 int ffmpeg_id;
00028 AVCodec *decoder;
00029 AVCodecContext *decoder_context;
00030 int decode_initialized;
00031 } quicktime_wma_codec_t;
00032
00033
00034
00035
00036 #define OUTPUT_ALLOCATION 0x100000
00037
00038 static int delete_codec(quicktime_audio_map_t *atrack)
00039 {
00040 quicktime_wma_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
00041
00042 if(codec->decode_initialized)
00043 {
00044 pthread_mutex_lock(&ffmpeg_lock);
00045 avcodec_close(codec->decoder_context);
00046 free(codec->decoder_context);
00047 pthread_mutex_unlock(&ffmpeg_lock);
00048 codec->decode_initialized = 0;
00049 }
00050
00051 if(codec->work_buffer)
00052 free(codec->work_buffer);
00053 if(codec->packet_buffer)
00054 free(codec->packet_buffer);
00055 free(codec);
00056 }
00057
00058
00059
00060 static int init_decode(quicktime_audio_map_t *track_map,
00061 quicktime_wma_codec_t *codec)
00062 {
00063 if(!codec->decode_initialized)
00064 {
00065 quicktime_trak_t *trak = track_map->track;
00066 pthread_mutex_lock(&ffmpeg_lock);
00067 if(!ffmpeg_initialized)
00068 {
00069 ffmpeg_initialized = 1;
00070 avcodec_init();
00071 avcodec_register_all();
00072 }
00073
00074 codec->decoder = avcodec_find_decoder(codec->ffmpeg_id);
00075 if(!codec->decoder)
00076 {
00077 printf("init_decode: avcodec_find_decoder returned NULL.\n");
00078 return 1;
00079 }
00080 codec->decoder_context = avcodec_alloc_context();
00081 codec->decoder_context->sample_rate = trak->mdia.minf.stbl.stsd.table[0].sample_rate;
00082 codec->decoder_context->channels = track_map->channels;
00083 if(avcodec_open(codec->decoder_context, codec->decoder) < 0)
00084 {
00085 printf("init_decode: avcodec_open failed.\n");
00086 return 1;
00087 }
00088 pthread_mutex_unlock(&ffmpeg_lock);
00089
00090 codec->work_buffer = malloc(2 * track_map->channels * OUTPUT_ALLOCATION);
00091 codec->output_allocated = OUTPUT_ALLOCATION;
00092 }
00093 return 0;
00094 }
00095
00096 static int decode(quicktime_t *file,
00097 int16_t *output_i,
00098 float *output_f,
00099 long samples,
00100 int track,
00101 int channel)
00102 {
00103 quicktime_audio_map_t *track_map = &(file->atracks[track]);
00104 quicktime_wma_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
00105 quicktime_trak_t *trak = track_map->track;
00106 long current_position = track_map->current_position;
00107 long end_position = current_position + samples;
00108 int try = 0;
00109 int result = 0;
00110 int i, j;
00111 int sample_size = 2 * track_map->channels;
00112
00113 if(output_i) bzero(output_i, sizeof(int16_t) * samples);
00114 if(output_f) bzero(output_f, sizeof(float) * samples);
00115
00116 if(samples > OUTPUT_ALLOCATION)
00117 printf("decode: can't read more than %d samples at a time.\n", OUTPUT_ALLOCATION);
00118
00119 result = init_decode(track_map, codec);
00120 if(result) return 1;
00121
00122
00123 if(current_position < codec->output_position ||
00124 current_position > codec->output_position + codec->output_size ||
00125 !codec->decode_initialized)
00126 {
00127 quicktime_chunk_of_sample(&codec->output_position,
00128 &codec->chunk,
00129 trak,
00130 current_position);
00131
00132
00133
00134 codec->output_size = 0;
00135 codec->decode_initialized = 1;
00136 }
00137
00138
00139 while(codec->output_position + codec->output_size <
00140 current_position + samples &&
00141 try < 256)
00142 {
00143
00144 int64_t chunk_offset = 0;
00145 int chunk_samples = quicktime_chunk_samples(trak, codec->chunk);
00146 int chunk_size = quicktime_chunk_bytes(file,
00147 &chunk_offset,
00148 codec->chunk,
00149 trak);
00150
00151
00152 int max_samples = 32768;
00153 int max_bytes = max_samples * sample_size;
00154 int bytes_decoded = 0;
00155 printf("decode 2 %x %llx %llx\n", chunk_size, chunk_offset, chunk_offset + chunk_size);
00156
00157
00158 if(codec->packet_allocated < chunk_size &&
00159 codec->packet_buffer)
00160 {
00161 free(codec->packet_buffer);
00162 codec->packet_buffer = 0;
00163 }
00164
00165 if(!codec->packet_buffer)
00166 {
00167 codec->packet_buffer = calloc(1, chunk_size);
00168 codec->packet_allocated = chunk_size;
00169 }
00170
00171
00172 if(max_bytes + codec->output_size * sample_size > codec->output_allocated * sample_size)
00173 {
00174 char *new_output = calloc(1, max_bytes + codec->output_size * sample_size);
00175 if(codec->work_buffer)
00176 {
00177 memcpy(new_output, codec->work_buffer, codec->output_size * sample_size);
00178 free(codec->work_buffer);
00179 }
00180 codec->work_buffer = new_output;
00181 codec->output_allocated = max_bytes + codec->output_size * sample_size;
00182 }
00183
00184 quicktime_set_position(file, chunk_offset);
00185 result = !quicktime_read_data(file, codec->packet_buffer, chunk_size);
00186 if(result) break;
00187
00188
00189 pthread_mutex_lock(&ffmpeg_lock);
00190 result = avcodec_decode_audio(codec->decoder_context,
00191 (int16_t*)(codec->work_buffer + codec->output_size * sample_size),
00192 &bytes_decoded,
00193 codec->packet_buffer,
00194 chunk_size);
00195 pthread_mutex_unlock(&ffmpeg_lock);
00196 if(bytes_decoded <= 0)
00197 {
00198 try++;
00199 }
00200 else
00201 {
00202 if(codec->output_size * sample_size + bytes_decoded > codec->output_allocated * sample_size)
00203 printf("decode: FYI: bytes_decoded=%d is greater than output_allocated=%d\n",
00204 codec->output_size * sample_size + bytes_decoded,
00205 codec->output_allocated);
00206 codec->output_size += bytes_decoded / sample_size;
00207 try = 0;
00208 }
00209 codec->chunk++;
00210 }
00211
00212
00213
00214 if(output_i)
00215 {
00216 int16_t *pcm_ptr = (int16_t*)codec->work_buffer +
00217 (current_position - codec->output_position) * track_map->channels +
00218 channel;
00219 for(i = current_position - codec->output_position, j = 0;
00220 j < samples && i < codec->output_size;
00221 j++, i++)
00222 {
00223 output_i[j] = *pcm_ptr;
00224 pcm_ptr += track_map->channels;
00225 }
00226 }
00227 else
00228 if(output_f)
00229 {
00230 int16_t *pcm_ptr = (int16_t*)codec->work_buffer +
00231 (current_position - codec->output_position) * track_map->channels +
00232 channel;
00233 for(i = current_position - codec->output_position, j = 0;
00234 j < samples && i < codec->output_size;
00235 j++, i++)
00236 {
00237 output_i[j] = (float)*pcm_ptr / (float)32767;
00238 pcm_ptr += track_map->channels;
00239 }
00240 }
00241
00242
00243 if(codec->output_size > OUTPUT_ALLOCATION)
00244 {
00245 int sample_diff = codec->output_size - OUTPUT_ALLOCATION;
00246 int byte_diff = sample_diff * sample_size;
00247 memcpy(codec->work_buffer,
00248 codec->work_buffer + byte_diff,
00249 OUTPUT_ALLOCATION * sample_size);
00250 codec->output_size -= sample_diff;
00251 codec->output_position += sample_diff;
00252 }
00253
00254 return 0;
00255 }
00256
00257
00258
00259
00260
00261
00262
00263 static void init_codec_common(quicktime_audio_map_t *atrack)
00264 {
00265 quicktime_wma_codec_t *codec;
00266 quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
00267
00268
00269 codec_base->delete_acodec = delete_codec;
00270 codec_base->decode_audio = decode;
00271
00272
00273
00274 codec = codec_base->priv = calloc(1, sizeof(quicktime_wma_codec_t));
00275 }
00276
00277
00278 void quicktime_init_codec_wmav1(quicktime_audio_map_t *atrack)
00279 {
00280 quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
00281 quicktime_wma_codec_t *codec;
00282 init_codec_common(atrack);
00283
00284 codec = codec_base->priv;
00285 codec_base->fourcc = QUICKTIME_WMA;
00286 codec_base->title = "Win Media Audio 1";
00287 codec_base->desc = "Win Media Audio 1";
00288 codec_base->wav_id = 0x160;
00289 codec->ffmpeg_id = CODEC_ID_WMAV1;
00290 }
00291
00292
00293 void quicktime_init_codec_wmav2(quicktime_audio_map_t *atrack)
00294 {
00295 quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
00296 quicktime_wma_codec_t *codec;
00297 init_codec_common(atrack);
00298
00299 codec = codec_base->priv;
00300 codec_base->fourcc = QUICKTIME_WMA;
00301 codec_base->title = "Win Media Audio 2";
00302 codec_base->desc = "Win Media Audio 2";
00303 codec_base->wav_id = 0x161;
00304 codec->ffmpeg_id = CODEC_ID_WMAV2;
00305 }