"Fossies" - the Fresh Open Source Software Archive

Member "quicktime4linux-2.3/wma.c" (9 Jan 2007, 8208 Bytes) of package /linux/privat/old/quicktime4linux-2.3-src.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #include "avcodec.h"
    2 #include "funcprotos.h"
    3 #include "quicktime.h"
    4 #include <string.h>
    5 #include "wma.h"
    6 
    7 /* McRowesoft media player audio */
    8 /* WMA derivatives */
    9 
   10 typedef struct
   11 {
   12 // Sample output
   13     char *work_buffer;
   14 // Number of first sample in output relative to file
   15     int64_t output_position;
   16 // Number of samples in output buffer
   17     long output_size;
   18 // Number of samples allocated in output buffer
   19     long output_allocated;
   20     char *packet_buffer;
   21     int packet_allocated;
   22 // Current reading position in file
   23     int64_t chunk;
   24 
   25 
   26 
   27     int ffmpeg_id;
   28     AVCodec *decoder;
   29     AVCodecContext *decoder_context;
   30     int decode_initialized;
   31 } quicktime_wma_codec_t;
   32 
   33 
   34 
   35 // Default number of samples to allocate in work buffer
   36 #define OUTPUT_ALLOCATION 0x100000
   37 
   38 static int delete_codec(quicktime_audio_map_t *atrack)
   39 {
   40     quicktime_wma_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
   41 
   42     if(codec->decode_initialized)
   43     {
   44         pthread_mutex_lock(&ffmpeg_lock);
   45         avcodec_close(codec->decoder_context);
   46         free(codec->decoder_context);
   47         pthread_mutex_unlock(&ffmpeg_lock);
   48         codec->decode_initialized = 0;
   49     }
   50 
   51     if(codec->work_buffer)
   52         free(codec->work_buffer);
   53     if(codec->packet_buffer)
   54         free(codec->packet_buffer);
   55     free(codec);
   56 }
   57 
   58 
   59 
   60 static int init_decode(quicktime_audio_map_t *track_map,
   61     quicktime_wma_codec_t *codec)
   62 {
   63     if(!codec->decode_initialized)
   64     {
   65         quicktime_trak_t *trak = track_map->track;
   66         pthread_mutex_lock(&ffmpeg_lock);
   67         if(!ffmpeg_initialized)
   68         {
   69             ffmpeg_initialized = 1;
   70             avcodec_init();
   71             avcodec_register_all();
   72         }
   73 
   74         codec->decoder = avcodec_find_decoder(codec->ffmpeg_id);
   75         if(!codec->decoder)
   76         {
   77             printf("init_decode: avcodec_find_decoder returned NULL.\n");
   78             return 1;
   79         }
   80         codec->decoder_context = avcodec_alloc_context();
   81         codec->decoder_context->sample_rate = trak->mdia.minf.stbl.stsd.table[0].sample_rate;
   82         codec->decoder_context->channels = track_map->channels;
   83         if(avcodec_open(codec->decoder_context, codec->decoder) < 0)
   84         {
   85             printf("init_decode: avcodec_open failed.\n");
   86             return 1;
   87         }
   88         pthread_mutex_unlock(&ffmpeg_lock);
   89 
   90         codec->work_buffer = malloc(2 * track_map->channels * OUTPUT_ALLOCATION);
   91         codec->output_allocated = OUTPUT_ALLOCATION;
   92     }
   93     return 0;
   94 }
   95 
   96 static int decode(quicktime_t *file, 
   97                     int16_t *output_i, 
   98                     float *output_f, 
   99                     long samples, 
  100                     int track, 
  101                     int channel)
  102 {
  103     quicktime_audio_map_t *track_map = &(file->atracks[track]);
  104     quicktime_wma_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
  105     quicktime_trak_t *trak = track_map->track;
  106     long current_position = track_map->current_position;
  107     long end_position = current_position + samples;
  108     int try = 0;
  109     int result = 0;
  110     int i, j;
  111     int sample_size = 2 * track_map->channels;
  112 
  113     if(output_i) bzero(output_i, sizeof(int16_t) * samples);
  114     if(output_f) bzero(output_f, sizeof(float) * samples);
  115 
  116     if(samples > OUTPUT_ALLOCATION)
  117         printf("decode: can't read more than %d samples at a time.\n", OUTPUT_ALLOCATION);
  118 
  119     result = init_decode(track_map, codec);
  120     if(result) return 1;
  121 
  122 // Seeked outside output buffer's range or not initialized: restart
  123     if(current_position < codec->output_position ||
  124         current_position > codec->output_position + codec->output_size ||
  125         !codec->decode_initialized)
  126     {
  127         quicktime_chunk_of_sample(&codec->output_position, 
  128             &codec->chunk, 
  129             trak, 
  130             current_position);
  131 
  132 //printf("decode 1 %lld %d\n", codec->output_position, codec->chunk);
  133 // We know the first mp3 packet in the chunk has a pcm_offset from the encoding.
  134         codec->output_size = 0;
  135         codec->decode_initialized = 1;
  136     }
  137 
  138 // Decode chunks until output buffer covers requested range
  139     while(codec->output_position + codec->output_size <
  140         current_position + samples &&
  141         try < 256)
  142     {
  143 // Load chunk into work buffer
  144         int64_t chunk_offset = 0;
  145         int chunk_samples = quicktime_chunk_samples(trak, codec->chunk);
  146         int chunk_size = quicktime_chunk_bytes(file, 
  147             &chunk_offset,
  148             codec->chunk, 
  149             trak);
  150 // Getting invalid numbers for this
  151 //      int max_samples = chunk_samples * 2;
  152         int max_samples = 32768;
  153         int max_bytes = max_samples * sample_size;
  154         int bytes_decoded = 0;
  155 printf("decode 2 %x %llx %llx\n", chunk_size, chunk_offset, chunk_offset + chunk_size);
  156 
  157 // Allocate packet buffer
  158         if(codec->packet_allocated < chunk_size && 
  159             codec->packet_buffer)
  160         {
  161             free(codec->packet_buffer);
  162             codec->packet_buffer = 0;
  163         }
  164 
  165         if(!codec->packet_buffer)
  166         {
  167             codec->packet_buffer = calloc(1, chunk_size);
  168             codec->packet_allocated = chunk_size;
  169         }
  170 
  171 // Allocate work buffer
  172         if(max_bytes + codec->output_size * sample_size > codec->output_allocated * sample_size)
  173         {
  174             char *new_output = calloc(1, max_bytes + codec->output_size * sample_size);
  175             if(codec->work_buffer)
  176             {
  177                 memcpy(new_output, codec->work_buffer, codec->output_size * sample_size);
  178                 free(codec->work_buffer);
  179             }
  180             codec->work_buffer = new_output;
  181             codec->output_allocated = max_bytes + codec->output_size * sample_size;
  182         }
  183 
  184         quicktime_set_position(file, chunk_offset);
  185         result = !quicktime_read_data(file, codec->packet_buffer, chunk_size);
  186         if(result) break;
  187 
  188 // Decode chunk into work buffer.
  189         pthread_mutex_lock(&ffmpeg_lock);
  190         result = avcodec_decode_audio(codec->decoder_context, 
  191             (int16_t*)(codec->work_buffer + codec->output_size * sample_size), 
  192             &bytes_decoded,
  193             codec->packet_buffer, 
  194             chunk_size);
  195         pthread_mutex_unlock(&ffmpeg_lock);
  196         if(bytes_decoded <= 0)
  197         {
  198             try++;
  199         }
  200         else
  201         {
  202             if(codec->output_size * sample_size + bytes_decoded > codec->output_allocated * sample_size)
  203                 printf("decode: FYI: bytes_decoded=%d is greater than output_allocated=%d\n",
  204                     codec->output_size * sample_size + bytes_decoded,
  205                     codec->output_allocated);
  206             codec->output_size += bytes_decoded / sample_size;
  207             try = 0;
  208         }
  209         codec->chunk++;
  210     }
  211 
  212 //printf("decode 15 %d %lld %d\n", try, codec->output_position, codec->output_size);
  213 // Transfer to output
  214     if(output_i)
  215     {
  216         int16_t *pcm_ptr = (int16_t*)codec->work_buffer + 
  217             (current_position - codec->output_position) * track_map->channels +
  218             channel;
  219         for(i = current_position - codec->output_position, j = 0;
  220             j < samples && i < codec->output_size;
  221             j++, i++)
  222         {
  223             output_i[j] = *pcm_ptr;
  224             pcm_ptr += track_map->channels;
  225         }
  226     }
  227     else
  228     if(output_f)
  229     {
  230         int16_t *pcm_ptr = (int16_t*)codec->work_buffer + 
  231             (current_position - codec->output_position) * track_map->channels +
  232             channel;
  233         for(i = current_position - codec->output_position, j = 0;
  234             j < samples && i < codec->output_size;
  235             j++, i++)
  236         {
  237             output_i[j] = (float)*pcm_ptr / (float)32767;
  238             pcm_ptr += track_map->channels;
  239         }
  240     }
  241 
  242 // Delete excess output
  243     if(codec->output_size > OUTPUT_ALLOCATION)
  244     {
  245         int sample_diff = codec->output_size - OUTPUT_ALLOCATION;
  246         int byte_diff = sample_diff * sample_size;
  247         memcpy(codec->work_buffer,
  248             codec->work_buffer + byte_diff,
  249             OUTPUT_ALLOCATION * sample_size);
  250         codec->output_size -= sample_diff;
  251         codec->output_position += sample_diff;
  252     }
  253 
  254     return 0;
  255 }
  256 
  257 
  258 
  259 
  260 
  261 
  262 
  263 static void init_codec_common(quicktime_audio_map_t *atrack)
  264 {
  265     quicktime_wma_codec_t *codec;
  266     quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
  267 
  268 /* Init public items */
  269     codec_base->delete_acodec = delete_codec;
  270     codec_base->decode_audio = decode;
  271     
  272 
  273 /* Init private items */
  274     codec = codec_base->priv = calloc(1, sizeof(quicktime_wma_codec_t));
  275 }
  276 
  277 
  278 void quicktime_init_codec_wmav1(quicktime_audio_map_t *atrack)
  279 {
  280     quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
  281     quicktime_wma_codec_t *codec;
  282     init_codec_common(atrack);
  283 
  284     codec = codec_base->priv;
  285     codec_base->fourcc = QUICKTIME_WMA;
  286     codec_base->title = "Win Media Audio 1";
  287     codec_base->desc = "Win Media Audio 1";
  288     codec_base->wav_id = 0x160;
  289     codec->ffmpeg_id = CODEC_ID_WMAV1;
  290 }
  291 
  292 
  293 void quicktime_init_codec_wmav2(quicktime_audio_map_t *atrack)
  294 {
  295     quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
  296     quicktime_wma_codec_t *codec;
  297     init_codec_common(atrack);
  298     
  299     codec = codec_base->priv;
  300     codec_base->fourcc = QUICKTIME_WMA;
  301     codec_base->title = "Win Media Audio 2";
  302     codec_base->desc = "Win Media Audio 2";
  303     codec_base->wav_id = 0x161;
  304     codec->ffmpeg_id = CODEC_ID_WMAV2;
  305 }