"Fossies" - the Fresh Open Source Software Archive

Member "quicktime4linux-2.3/qdm2.c" (19 Jun 2008, 8658 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 <stdint.h>
    2 #include <string.h>
    3 
    4 #include "avcodec.h"
    5 #include "funcprotos.h"
    6 #include "quicktime.h"
    7 
    8 extern int ffmpeg_initialized;
    9 extern pthread_mutex_t ffmpeg_lock;
   10 
   11 
   12 typedef struct
   13 {
   14     int decoder_initialized;
   15     AVCodec *decoder;
   16     AVCodecContext *decoder_context;
   17     
   18 // Number of frames
   19     int frame_size;
   20     int max_frame_bytes;
   21 // Input samples interleaved
   22     int16_t *input_buffer;
   23 // Number of samples allocated
   24     int input_allocated;
   25 // Last sample decoded in the input buffer + 1
   26     int64_t input_end;
   27 // Total samples in input buffer
   28     int input_size;
   29 // Current write offset in input buffer
   30     int input_ptr;
   31     
   32     unsigned char *compressed_buffer;
   33     int compressed_size;
   34     int compressed_allocated;
   35     int16_t *temp_buffer;
   36 
   37 // Next chunk to decode sequentially
   38     int64_t current_chunk;
   39 } quicktime_qdm2_codec_t;
   40 
   41 #define MAX(x, y) ((x) > (y) ? (x) : (y))
   42 // Default number of samples to allocate in work buffer
   43 #define OUTPUT_ALLOCATION MAX(0x100000, AVCODEC_MAX_AUDIO_FRAME_SIZE * 2 * 2)
   44 
   45 
   46 
   47 
   48 
   49 static int delete_codec(quicktime_audio_map_t *atrack)
   50 {
   51     quicktime_qdm2_codec_t *codec = 
   52         ((quicktime_codec_t*)atrack->codec)->priv;
   53 
   54     if(codec->decoder_initialized)
   55     {
   56         avcodec_close(codec->decoder_context);
   57         free(codec->decoder_context);
   58     }
   59 
   60     if(codec->input_buffer) free(codec->input_buffer);
   61     if(codec->compressed_buffer) free(codec->compressed_buffer);
   62     if(codec->temp_buffer) free(codec->temp_buffer);
   63 
   64     free(codec);
   65 }
   66 
   67 void allocate_compressed(quicktime_qdm2_codec_t *codec, int size)
   68 {
   69     if(size > codec->compressed_allocated)
   70     {
   71         codec->compressed_buffer = realloc(codec->compressed_buffer, size);
   72         codec->compressed_allocated = size;
   73     }
   74 }
   75 
   76 static int decode(quicktime_t *file, 
   77                     int16_t *output_i, 
   78                     float *output_f, 
   79                     long samples, 
   80                     int track, 
   81                     int channel)
   82 {
   83     quicktime_audio_map_t *track_map = &(file->atracks[track]);
   84     quicktime_trak_t *trak = track_map->track;
   85     quicktime_qdm2_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
   86     quicktime_stsd_table_t *stsd_table = &trak->mdia.minf.stbl.stsd.table[0];
   87     int64_t current_position = track_map->current_position;
   88     int64_t end_position = current_position + samples;
   89     quicktime_frma_t *frma = &stsd_table->frma;
   90     int channels = track_map->channels;
   91     int i, j;
   92     int debug = 0;
   93     int64_t chunk_sample;
   94     
   95 
   96 
   97 // Initialize decoder
   98     if(!codec->decoder_initialized)
   99     {
  100         pthread_mutex_lock(&ffmpeg_lock);
  101         if(!ffmpeg_initialized)
  102         {
  103             ffmpeg_initialized = 1;
  104             avcodec_init();
  105             avcodec_register_all();
  106         }
  107 
  108         codec->decoder = avcodec_find_decoder(CODEC_ID_QDM2);
  109         if(!codec->decoder)
  110         {
  111             printf("qdm2.c: decode: no ffmpeg decoder found.\n");
  112             return 1;
  113         }
  114 
  115         uint32_t samplerate = trak->mdia.minf.stbl.stsd.table[0].sample_rate;
  116 
  117 // allocate the codec and fill in header
  118         AVCodecContext *context = codec->decoder_context = avcodec_alloc_context();
  119         codec->decoder_context->sample_rate = trak->mdia.minf.stbl.stsd.table[0].sample_rate;
  120         codec->decoder_context->channels = track_map->channels;
  121 
  122         if(frma->data && frma->data_size)
  123         {
  124             context->extradata = frma->data;
  125             context->extradata_size = frma->data_size;
  126         }
  127 
  128         if(file->cpus > 1)
  129         {
  130             avcodec_thread_init(context, file->cpus);
  131 // Not exactly user friendly.
  132 //          context->thread_count = file->cpus;
  133         }
  134     
  135         if(avcodec_open(context, codec->decoder) < 0)
  136         {
  137             printf("qdm2.c: decode: avcodec_open failed.\n");
  138             return 1;
  139         }
  140         pthread_mutex_unlock(&ffmpeg_lock);
  141         
  142         codec->input_buffer = calloc(sizeof(int16_t),
  143             track_map->channels * OUTPUT_ALLOCATION);
  144         codec->input_allocated = OUTPUT_ALLOCATION;
  145 
  146             
  147         codec->decoder_initialized = 1;
  148     }
  149 
  150 
  151     if(samples > OUTPUT_ALLOCATION)
  152     {
  153         printf("qdm2: decode: can't decode more than %p samples at a time.\n",
  154             OUTPUT_ALLOCATION);
  155         return 1;
  156     }
  157 
  158 
  159 
  160     if(debug)
  161     {
  162         printf("qdm2 decode: current_position=%lld end_position=%lld input_size=%d input_end=%lld\n",
  163             current_position,
  164             end_position,
  165             codec->input_size,
  166             codec->input_end);
  167     }
  168 
  169 // printf("qdm2 decode: current_position=%lld end_position=%lld chunk_sample=%lld chunk=%lld\n", 
  170 // current_position, 
  171 // end_position,
  172 // chunk_sample,
  173 // chunk);
  174 
  175 
  176     if(current_position < codec->input_end - codec->input_size ||
  177         current_position > codec->input_end)
  178     {
  179 // Desired start point is outside existing range.  Reposition buffer pointer
  180 // to start time of nearest chunk and start over.
  181         quicktime_chunk_of_sample(&chunk_sample, 
  182             &codec->current_chunk, 
  183             trak, 
  184             current_position);
  185         codec->input_size = 0;
  186         codec->input_ptr = 0;
  187         codec->input_end = chunk_sample;
  188     }
  189 
  190 // Decode complete chunks until samples is reached
  191     int total_chunks = trak->mdia.minf.stbl.stco.total_entries;
  192     while(codec->input_end < end_position)
  193     {
  194         int64_t offset = quicktime_chunk_to_offset(file, 
  195             trak, 
  196             codec->current_chunk);
  197         int64_t max_offset = quicktime_chunk_to_offset(file, 
  198             trak, 
  199             codec->current_chunk + 1);
  200         quicktime_set_position(file, offset);
  201         allocate_compressed(codec, 3);
  202 
  203         if(debug)
  204         {
  205             printf("qdm2 decode: input_end=%lld chunk=%d offset=0x%llx\n", 
  206                 codec->input_end, 
  207                 codec->current_chunk, 
  208                 offset);
  209         }
  210 
  211 // Read fragments of chunk
  212         while(1)
  213         {
  214 // Hit next chunk of audio
  215             if(max_offset > offset && quicktime_position(file) >= max_offset) break;
  216             if(!quicktime_read_data(file, 
  217                 codec->compressed_buffer + codec->compressed_size, 
  218                 3))
  219                 break;
  220             if(codec->compressed_buffer[codec->compressed_size] != 0x82)
  221             {
  222 //              printf("qdm2: decode: position=0x%llx\n", quicktime_position(file));
  223                 break;
  224             }
  225             int fragment_size = 3 + ((codec->compressed_buffer[codec->compressed_size + 1] << 8) |
  226                 codec->compressed_buffer[codec->compressed_size + 2]);
  227 // Sanity check
  228             if(fragment_size > OUTPUT_ALLOCATION) break;
  229 // Expand compressed buffer
  230             allocate_compressed(codec, 
  231                 codec->compressed_size + fragment_size + 1024);
  232             if(!quicktime_read_data(file, 
  233                 codec->compressed_buffer + codec->compressed_size + 3, 
  234                 fragment_size - 3))
  235                 break;
  236 
  237             codec->compressed_size += fragment_size;
  238 
  239 // Repeat this sequence until ffmpeg stops outputting samples
  240             while(1)
  241             {
  242                 if(!codec->temp_buffer)
  243                     codec->temp_buffer = calloc(sizeof(int16_t), OUTPUT_ALLOCATION);
  244                 int bytes_decoded = AVCODEC_MAX_AUDIO_FRAME_SIZE;
  245                 int result = avcodec_decode_audio2(codec->decoder_context, 
  246                     codec->temp_buffer,
  247                     &bytes_decoded,
  248                     codec->compressed_buffer, 
  249                     codec->compressed_size);
  250 
  251 // Shift compressed buffer
  252                 if(result > 0)
  253                 {
  254                     memcpy(codec->compressed_buffer,
  255                         codec->compressed_buffer + result,
  256                         codec->compressed_size - result);
  257                     codec->compressed_size -= result;
  258                 }
  259 
  260 //printf("avcodec_decode_audio result=%d bytes_decoded=%d fragment_size=%d codec->compressed_size=%d\n", 
  261 //result, bytes_decoded, fragment_size, codec->compressed_size);
  262 /*
  263  * static FILE *test = 0;
  264  * if(!test) test = fopen("/tmp/debug", "w");
  265  * fwrite(codec->temp_buffer, 1, bytes_decoded, test);
  266  * fflush(test);
  267  */
  268                 for(i = 0; i < bytes_decoded / channels / sizeof(int16_t); i++)
  269                 {
  270                     for(j = 0; j < channels; j++)
  271                         codec->input_buffer[codec->input_ptr * channels + j] =
  272                             codec->temp_buffer[i * channels + j];
  273                     codec->input_ptr++;
  274                     if(codec->input_ptr >= codec->input_allocated)
  275                         codec->input_ptr = 0;
  276                 }
  277                 codec->input_end += bytes_decoded / channels / sizeof(int16_t);
  278                 codec->input_size += bytes_decoded / channels / sizeof(int16_t);
  279 
  280                 if(bytes_decoded <= 0) break;
  281             }
  282         }
  283 
  284         codec->current_chunk++;
  285         if(codec->current_chunk >= total_chunks) break;
  286     }
  287 
  288 // Transfer from buffer to output
  289     int input_ptr = codec->input_ptr - (codec->input_end - current_position);
  290     if(input_ptr < 0) input_ptr += codec->input_allocated;
  291     if(output_i)
  292     {
  293         for(i = 0; i < samples; i++)
  294         {
  295             output_i[i] = codec->input_buffer[input_ptr * channels + channel];
  296             input_ptr++;
  297             if(input_ptr >= codec->input_allocated) input_ptr = 0;
  298         }
  299     }
  300     else
  301     if(output_f)
  302     {
  303         for(i = 0; i < samples; i++)
  304         {
  305             output_f[i] = (float)codec->input_buffer[input_ptr * channels + channel] / 32768.0;
  306             input_ptr++;
  307             if(input_ptr >= codec->input_allocated) input_ptr = 0;
  308         }
  309     }
  310     return 0;
  311 }
  312 
  313 
  314 
  315 
  316 
  317 void quicktime_init_codec_qdm2(quicktime_audio_map_t *atrack)
  318 {
  319     quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
  320     codec_base->priv = calloc(1, sizeof(quicktime_qdm2_codec_t));
  321     codec_base->delete_acodec = delete_codec;
  322     codec_base->decode_audio = decode;
  323     codec_base->encode_audio = 0;
  324     codec_base->set_parameter = 0;
  325     codec_base->flush = 0;
  326     codec_base->fourcc = "QDM2";
  327     codec_base->title = "QDesign Music 2";
  328     codec_base->desc = "QDesign Music 2";
  329 }
  330 
  331 
  332 
  333