"Fossies" - the Fresh Open Source Software Archive

Member "quicktime4linux-2.3/wmx2.c" (9 Jan 2007, 13004 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 "qtprivate.h"
    2 #include "quicktime.h"
    3 #include "wmx2.h"
    4 
    5 typedef struct
    6 {
    7 /* During decoding the work_buffer contains the most recently read chunk. */
    8 /* During encoding the work_buffer contains interlaced overflow samples  */
    9 /* from the last chunk written. */
   10     int16_t *write_buffer;
   11     unsigned char *read_buffer;    /* Temporary buffer for drive reads. */
   12 
   13 /* Starting information for all channels during encoding a chunk. */
   14     int *last_samples, *last_indexes;
   15     long chunk; /* Number of chunk in work buffer */
   16     int buffer_channel; /* Channel of work buffer */
   17 
   18 /* Number of samples in largest chunk read. */
   19 /* Number of samples plus overflow in largest chunk write, interlaced. */
   20     long write_size;     /* Size of write buffer. */
   21     long read_size;     /* Size of read buffer. */
   22 } quicktime_wmx2_codec_t;
   23 
   24 static int quicktime_wmx2_step[89] = 
   25 {
   26     7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
   27     19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
   28     50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
   29     130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
   30     337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
   31     876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
   32     2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
   33     5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
   34     15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
   35 };
   36 
   37 static int quicktime_wmx2_index[16] = 
   38 {
   39     -1, -1, -1, -1, 2, 4, 6, 8,
   40     -1, -1, -1, -1, 2, 4, 6, 8
   41 };
   42 
   43 /* ================================== private for wmx2 */
   44 #define HEADER_SIZE 3
   45 
   46 static int wmx2_decode_sample(int *predictor, int *nibble, int *index, int *step)
   47 {
   48     int difference, sign;
   49 
   50 /* Get new index value */
   51     *index += quicktime_wmx2_index[*nibble];
   52 
   53     if(*index < 0) *index = 0; 
   54     else 
   55     if(*index > 88) *index = 88;
   56 
   57 /* Get sign and magnitude from *nibble */
   58     sign = *nibble & 8;
   59     *nibble = *nibble & 7;
   60 
   61 /* Get difference */
   62     difference = *step >> 3;
   63     if(*nibble & 4) difference += *step;
   64     if(*nibble & 2) difference += *step >> 1;
   65     if(*nibble & 1) difference += *step >> 2;
   66 
   67 /* Predict value */
   68     if(sign) 
   69     *predictor -= difference;
   70     else 
   71     *predictor += difference;
   72 
   73     if(*predictor > 32767) *predictor = 32767;
   74     else
   75     if(*predictor < -32768) *predictor = -32768;
   76 
   77 /* Update the step value */
   78     *step = quicktime_wmx2_step[*index];
   79 
   80     return 0;
   81 }
   82 
   83 
   84 static int wmx2_decode_block(quicktime_audio_map_t *atrack, int16_t *output, unsigned char *input, int samples)
   85 {
   86     int predictor;
   87     int index;
   88     int step;
   89     int i, nibble, nibble_count, block_size;
   90     unsigned char *block_ptr;
   91     int16_t *output_end = output + samples;
   92     quicktime_wmx2_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
   93 
   94 /* Get the chunk header */
   95     predictor = *input++ << 8;
   96     predictor |= *input++;
   97     if(predictor & 0x8000) predictor -= 0x10000;
   98     index = *input++;
   99     if(index > 88) index = 88;
  100 
  101 /*printf("input %d %d\n", predictor, index); */
  102     step = quicktime_wmx2_step[index];
  103 
  104 /* Read the input buffer sequentially, one nibble at a time */
  105     nibble_count = 0;
  106     while(output < output_end)
  107     {
  108         nibble = nibble_count ? (*input++  >> 4) & 0x0f : *input & 0x0f;
  109 
  110         wmx2_decode_sample(&predictor, &nibble, &index, &step);
  111         *output++ = predictor;
  112 
  113         nibble_count ^= 1;
  114     }
  115 }
  116 
  117 static int wmx2_encode_sample(int *last_sample, int *last_index, int *nibble, int next_sample)
  118 {
  119     int difference, new_difference, mask, step;
  120 
  121     difference = next_sample - *last_sample;
  122     *nibble = 0;
  123     step = quicktime_wmx2_step[*last_index];
  124     new_difference = step >> 3;
  125 
  126     if(difference < 0)
  127     {
  128         *nibble = 8;
  129         difference = -difference;
  130     }
  131 
  132     mask = 4;
  133     while(mask)
  134     {
  135         if(difference >= step)
  136         {
  137             *nibble |= mask;
  138             difference -= step;
  139             new_difference += step;
  140         }
  141 
  142         step >>= 1;
  143         mask >>= 1;
  144     }
  145 
  146     if(*nibble & 8)
  147         *last_sample -= new_difference;
  148     else
  149         *last_sample += new_difference;
  150 
  151     if(*last_sample > 32767) *last_sample = 32767;
  152     else
  153     if(*last_sample < -32767) *last_sample = -32767;
  154 
  155     *last_index += quicktime_wmx2_index[*nibble];
  156 
  157     if(*last_index < 0) *last_index = 0;
  158     else
  159     if(*last_index > 88) *last_index= 88;
  160 
  161     return 0;
  162 }
  163 
  164 static int wmx2_encode_block(quicktime_audio_map_t *atrack, unsigned char *output, int16_t *input, int step, int channel, int samples)
  165 {
  166     quicktime_wmx2_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
  167     int i, nibble_count = 0, nibble, header;
  168 
  169 /* Get a fake starting sample */
  170     header = codec->last_samples[channel];
  171 /*printf("output %d %d\n", header, codec->last_indexes[channel]); */
  172 /* Force rounding. */
  173 /*  if(header < 0x7fc0) header += 0x40; */
  174 /*  header &= 0xff80; */
  175     if(header < 0) header += 0x10000;
  176     *output++ = (header & 0xff00) >> 8;
  177     *output++ = (header & 0xff);
  178     *output++ = (codec->last_indexes[channel] & 0x7f);
  179 
  180     for(i = 0; i < samples; i++)
  181     {
  182         wmx2_encode_sample(&(codec->last_samples[channel]), 
  183                             &(codec->last_indexes[channel]), 
  184                             &nibble, 
  185                             *input);
  186 
  187         if(nibble_count)
  188             *output++ |= (nibble << 4);
  189         else
  190             *output = nibble;
  191 
  192         input += step;
  193         nibble_count ^= 1;
  194     }
  195 
  196     return 0;
  197 }
  198 
  199 /* Convert the number of samples in a chunk into the number of bytes in that */
  200 /* chunk.  The number of samples in a chunk should end on a block boundary. */
  201 static long wmx2_samples_to_bytes(long samples, int channels)
  202 {
  203     long bytes = samples / 2;
  204     if(bytes * 2 < samples) bytes++;
  205     bytes *= channels;
  206     bytes += HEADER_SIZE * channels;
  207     return bytes;
  208 }
  209 
  210 /* Decode the chunk into the work buffer */
  211 static int wmx2_decode_chunk(quicktime_t *file, int track, long chunk, int channel)
  212 {
  213     int result = 0;
  214     int i, j;
  215     long chunk_samples, chunk_bytes;
  216     unsigned char *chunk_ptr, *block_ptr;
  217     quicktime_trak_t *trak = file->atracks[track].track;
  218     quicktime_wmx2_codec_t *codec = 
  219         ((quicktime_codec_t*)file->atracks[track].codec)->priv;
  220 
  221 /* Get the byte count to read. */
  222     chunk_samples = quicktime_chunk_samples(trak, chunk);
  223     chunk_bytes = wmx2_samples_to_bytes(chunk_samples, file->atracks[track].channels);
  224 
  225 /* Get the buffer to read into. */
  226     if(codec->write_buffer && codec->write_size < chunk_samples)
  227     {
  228         free(codec->write_buffer);
  229         codec->write_buffer = 0;
  230     }
  231 
  232     if(!codec->write_buffer)
  233     {
  234         codec->write_size = chunk_samples;
  235         codec->write_buffer = malloc(sizeof(int16_t) * codec->write_size);
  236     }
  237 
  238     if(codec->read_buffer && codec->read_size < chunk_bytes)
  239     {
  240         free(codec->read_buffer);
  241         codec->read_buffer = 0;
  242     }
  243 
  244     if(!codec->read_buffer)
  245     {
  246         codec->read_size = chunk_bytes;
  247         codec->read_buffer = malloc(codec->read_size);
  248     }
  249 
  250 /* codec->work_size now holds the number of samples in the last chunk */
  251 /* codec->read_size now holds number of bytes in the last read buffer */
  252 
  253 /* Read the entire chunk regardless of where the desired sample range starts. */
  254     result = quicktime_read_chunk(file, codec->read_buffer, track, chunk, 0, chunk_bytes);
  255 
  256 /* Now decode the chunk, one block at a time, until the total samples in the chunk */
  257 /* is reached. */
  258 
  259     if(!result)
  260     {
  261         block_ptr = codec->read_buffer;
  262         for(j = 0; j < file->atracks[track].channels; j++)
  263         {
  264             if(j == channel)
  265                 wmx2_decode_block(&(file->atracks[track]), codec->write_buffer, block_ptr, chunk_samples);
  266 
  267             block_ptr += chunk_bytes / file->atracks[track].channels;
  268         }
  269     }
  270     codec->buffer_channel = channel;
  271     codec->chunk = chunk;
  272 
  273     return result;
  274 }
  275 
  276 
  277 /* =================================== public for wmx2 */
  278 
  279 static int decode(quicktime_t *file, 
  280                     int16_t *output_i, 
  281                     float *output_f,
  282                     long samples, 
  283                     int track, 
  284                     int channel)
  285 {
  286     int result = 0;
  287     long chunk, chunk_sample, chunk_bytes, chunk_samples;
  288     long i, chunk_start, chunk_end;
  289     quicktime_trak_t *trak = file->atracks[track].track;
  290     quicktime_wmx2_codec_t *codec = 
  291         ((quicktime_codec_t*)file->atracks[track].codec)->priv;
  292 
  293 /* Get the first chunk with this routine and then increase the chunk number. */
  294     quicktime_chunk_of_sample(&chunk_sample, &chunk, trak, file->atracks[track].current_position);
  295 
  296 /* Read chunks until the output is full. */
  297     for(i = 0; i < samples && !result; )
  298     {
  299 /* Get chunk we're on. */
  300         chunk_samples = quicktime_chunk_samples(trak, chunk);
  301 
  302         if(!codec->write_buffer ||
  303             codec->chunk != chunk ||
  304             codec->buffer_channel != channel)
  305         {
  306 /* read a new chunk if necessary */
  307             result = wmx2_decode_chunk(file, track, chunk, channel);
  308         }
  309 
  310 /* Get boundaries from the chunk */
  311         chunk_start = 0;
  312         if(chunk_sample < file->atracks[track].current_position)
  313             chunk_start = file->atracks[track].current_position - chunk_sample;
  314 
  315         chunk_end = chunk_samples;
  316         if(chunk_sample + chunk_end > file->atracks[track].current_position + samples)
  317             chunk_end = file->atracks[track].current_position + samples - chunk_sample;
  318 
  319 /* Read from the chunk */
  320         if(output_i)
  321         {
  322             while(chunk_start < chunk_end)
  323             {
  324                 output_i[i++] = codec->write_buffer[chunk_start++];
  325             }
  326         }
  327         else
  328         if(output_f)
  329         {
  330             while(chunk_start < chunk_end)
  331             {
  332                 output_f[i++] = (float)codec->write_buffer[chunk_start++] / 32767;
  333             }
  334         }
  335 
  336         chunk++;
  337         chunk_sample += chunk_samples;
  338     }
  339 
  340     return result;
  341 }
  342 
  343 static int encode(quicktime_t *file, 
  344                         int16_t **input_i, 
  345                         float **input_f, 
  346                         int track, 
  347                         long samples)
  348 {
  349     int result = 0;
  350     long i, j, step;
  351     long chunk_bytes;
  352     long offset;
  353     quicktime_audio_map_t *track_map = &(file->atracks[track]);
  354     quicktime_wmx2_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
  355     quicktime_trak_t *trak = track_map->track;
  356     int16_t *input_ptr;
  357     unsigned char *output_ptr;
  358     quicktime_atom_t chunk_atom;
  359 
  360 /* Get buffer sizes */
  361     if(codec->write_buffer && codec->write_size < samples * track_map->channels)
  362     {
  363 /* Create new buffer */
  364         long new_size = samples * track_map->channels;
  365         int16_t *new_buffer = malloc(sizeof(int16_t) * new_size);
  366 
  367 /* Swap pointers. */
  368         free(codec->write_buffer);
  369         codec->write_buffer = new_buffer;
  370         codec->write_size = new_size;
  371     }
  372     else
  373     if(!codec->write_buffer)
  374     {
  375 /* No buffer in the first place. */
  376         codec->write_size = samples * track_map->channels;
  377         codec->write_buffer = malloc(sizeof(int16_t) * codec->write_size);
  378     }
  379 
  380 /* Get output size */
  381     chunk_bytes = wmx2_samples_to_bytes(samples, track_map->channels);
  382     if(codec->read_buffer && codec->read_size < chunk_bytes)
  383     {
  384         free(codec->read_buffer);
  385         codec->read_buffer = 0;
  386     }
  387 
  388     if(!codec->read_buffer)
  389     {
  390         codec->read_buffer = malloc(chunk_bytes);
  391         codec->read_size = chunk_bytes;
  392     }
  393 
  394     if(!codec->last_samples)
  395     {
  396         codec->last_samples = malloc(sizeof(int) * track_map->channels);
  397         for(i = 0; i < track_map->channels; i++)
  398         {
  399             codec->last_samples[i] = 0;
  400         }
  401     }
  402 
  403     if(!codec->last_indexes)
  404     {
  405         codec->last_indexes = malloc(sizeof(int) * track_map->channels);
  406         for(i = 0; i < track_map->channels; i++)
  407         {
  408             codec->last_indexes[i] = 0;
  409         }
  410     }
  411 
  412 /* Arm the input buffer */
  413     step = track_map->channels;
  414     for(j = 0; j < track_map->channels; j++)
  415     {
  416         input_ptr = codec->write_buffer + j;
  417 
  418         if(input_i)
  419         {
  420             for(i = 0; i < samples; i++)
  421             {
  422                 *input_ptr = input_i[j][i];
  423                 input_ptr += step;
  424             }
  425         }
  426         else
  427         if(input_f)
  428         {
  429             for(i = 0; i < samples; i++)
  430             {
  431                 *input_ptr = (int16_t)(input_f[j][i] * 32767);
  432                 input_ptr += step;
  433             }
  434         }
  435     }
  436 
  437 /* Encode from the input buffer to the read_buffer. */
  438     input_ptr = codec->write_buffer;
  439     output_ptr = codec->read_buffer;
  440 
  441     for(j = 0; j < track_map->channels; j++)
  442     {
  443         wmx2_encode_block(track_map, output_ptr, input_ptr + j, track_map->channels, j, samples);
  444 
  445         output_ptr += chunk_bytes / track_map->channels;
  446     }
  447 
  448     if(samples)
  449     {
  450         offset = quicktime_position(file);
  451         quicktime_write_chunk_header(file, trak, &chunk_atom);
  452         result = quicktime_write_data(file, codec->read_buffer, chunk_bytes);
  453         if(result)
  454             result = 0; 
  455         else 
  456             result = 1; /* defeat fwrite's return */
  457         quicktime_write_chunk_footer(file, 
  458             trak,
  459             track_map->current_chunk,
  460             &chunk_atom, 
  461             1);
  462         track_map->current_chunk++;
  463     }
  464 
  465     return result;
  466 }
  467 
  468 static int delete_codec(quicktime_audio_map_t *atrack)
  469 {
  470     quicktime_wmx2_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
  471     if(codec->write_buffer) free(codec->write_buffer);
  472     if(codec->read_buffer) free(codec->read_buffer);
  473     if(codec->last_samples) free(codec->last_samples);
  474     if(codec->last_indexes) free(codec->last_indexes);
  475     codec->last_samples = 0;
  476     codec->last_indexes = 0;
  477     codec->read_buffer = 0;
  478     codec->write_buffer = 0;
  479     codec->chunk = 0;
  480     codec->buffer_channel = 0; /* Channel of work buffer */
  481     codec->write_size = 0;          /* Size of work buffer */
  482     codec->read_size = 0;
  483     free(codec);
  484     return 0;
  485 }
  486 
  487 void quicktime_init_codec_wmx2(quicktime_audio_map_t *atrack)
  488 {
  489     quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
  490 
  491 /* Init public items */
  492     codec_base->priv = calloc(1, sizeof(quicktime_wmx2_codec_t));
  493     codec_base->delete_acodec = delete_codec;
  494     codec_base->decode_video = 0;
  495     codec_base->encode_video = 0;
  496     codec_base->decode_audio = decode;
  497     codec_base->encode_audio = encode;
  498     codec_base->fourcc = QUICKTIME_WMX2;
  499     codec_base->title = "IMA4 on steroids";
  500     codec_base->desc = "IMA4 on steroids. (Not standardized)";
  501     codec_base->wav_id = 0x11;
  502 }