Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * RoQ audio encoder
  3.  *
  4.  * Copyright (c) 2005 Eric Lasota
  5.  *    Based on RoQ specs (c)2001 Tim Ferguson
  6.  *
  7.  * This file is part of FFmpeg.
  8.  *
  9.  * FFmpeg is free software; you can redistribute it and/or
  10.  * modify it under the terms of the GNU Lesser General Public
  11.  * License as published by the Free Software Foundation; either
  12.  * version 2.1 of the License, or (at your option) any later version.
  13.  *
  14.  * FFmpeg is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17.  * Lesser General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU Lesser General Public
  20.  * License along with FFmpeg; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22.  */
  23.  
  24. #include "avcodec.h"
  25. #include "bytestream.h"
  26. #include "internal.h"
  27. #include "mathops.h"
  28.  
  29. #define ROQ_FRAME_SIZE           735
  30. #define ROQ_HEADER_SIZE   8
  31.  
  32. #define MAX_DPCM (127*127)
  33.  
  34.  
  35. typedef struct ROQDPCMContext {
  36.     short lastSample[2];
  37.     int input_frames;
  38.     int buffered_samples;
  39.     int16_t *frame_buffer;
  40.     int64_t first_pts;
  41. } ROQDPCMContext;
  42.  
  43.  
  44. static av_cold int roq_dpcm_encode_close(AVCodecContext *avctx)
  45. {
  46.     ROQDPCMContext *context = avctx->priv_data;
  47.  
  48.     av_freep(&context->frame_buffer);
  49.  
  50.     return 0;
  51. }
  52.  
  53. static av_cold int roq_dpcm_encode_init(AVCodecContext *avctx)
  54. {
  55.     ROQDPCMContext *context = avctx->priv_data;
  56.     int ret;
  57.  
  58.     if (avctx->channels > 2) {
  59.         av_log(avctx, AV_LOG_ERROR, "Audio must be mono or stereo\n");
  60.         return AVERROR(EINVAL);
  61.     }
  62.     if (avctx->sample_rate != 22050) {
  63.         av_log(avctx, AV_LOG_ERROR, "Audio must be 22050 Hz\n");
  64.         return AVERROR(EINVAL);
  65.     }
  66.  
  67.     avctx->frame_size = ROQ_FRAME_SIZE;
  68.     avctx->bit_rate   = (ROQ_HEADER_SIZE + ROQ_FRAME_SIZE * avctx->channels) *
  69.                         (22050 / ROQ_FRAME_SIZE) * 8;
  70.  
  71.     context->frame_buffer = av_malloc(8 * ROQ_FRAME_SIZE * avctx->channels *
  72.                                       sizeof(*context->frame_buffer));
  73.     if (!context->frame_buffer) {
  74.         ret = AVERROR(ENOMEM);
  75.         goto error;
  76.     }
  77.  
  78.     context->lastSample[0] = context->lastSample[1] = 0;
  79.  
  80.     return 0;
  81. error:
  82.     roq_dpcm_encode_close(avctx);
  83.     return ret;
  84. }
  85.  
  86. static unsigned char dpcm_predict(short *previous, short current)
  87. {
  88.     int diff;
  89.     int negative;
  90.     int result;
  91.     int predicted;
  92.  
  93.     diff = current - *previous;
  94.  
  95.     negative = diff<0;
  96.     diff = FFABS(diff);
  97.  
  98.     if (diff >= MAX_DPCM)
  99.         result = 127;
  100.     else {
  101.         result = ff_sqrt(diff);
  102.         result += diff > result*result+result;
  103.     }
  104.  
  105.     /* See if this overflows */
  106.  retry:
  107.     diff = result*result;
  108.     if (negative)
  109.         diff = -diff;
  110.     predicted = *previous + diff;
  111.  
  112.     /* If it overflows, back off a step */
  113.     if (predicted > 32767 || predicted < -32768) {
  114.         result--;
  115.         goto retry;
  116.     }
  117.  
  118.     /* Add the sign bit */
  119.     result |= negative << 7;   //if (negative) result |= 128;
  120.  
  121.     *previous = predicted;
  122.  
  123.     return result;
  124. }
  125.  
  126. static int roq_dpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
  127.                                  const AVFrame *frame, int *got_packet_ptr)
  128. {
  129.     int i, stereo, data_size, ret;
  130.     const int16_t *in = frame ? (const int16_t *)frame->data[0] : NULL;
  131.     uint8_t *out;
  132.     ROQDPCMContext *context = avctx->priv_data;
  133.  
  134.     stereo = (avctx->channels == 2);
  135.  
  136.     if (!in && context->input_frames >= 8)
  137.         return 0;
  138.  
  139.     if (in && context->input_frames < 8) {
  140.         memcpy(&context->frame_buffer[context->buffered_samples * avctx->channels],
  141.                in, avctx->frame_size * avctx->channels * sizeof(*in));
  142.         context->buffered_samples += avctx->frame_size;
  143.         if (context->input_frames == 0)
  144.             context->first_pts = frame->pts;
  145.         if (context->input_frames < 7) {
  146.             context->input_frames++;
  147.             return 0;
  148.         }
  149.     }
  150.     if (context->input_frames < 8)
  151.         in = context->frame_buffer;
  152.  
  153.     if (stereo) {
  154.         context->lastSample[0] &= 0xFF00;
  155.         context->lastSample[1] &= 0xFF00;
  156.     }
  157.  
  158.     if (context->input_frames == 7)
  159.         data_size = avctx->channels * context->buffered_samples;
  160.     else
  161.         data_size = avctx->channels * avctx->frame_size;
  162.  
  163.     if ((ret = ff_alloc_packet2(avctx, avpkt, ROQ_HEADER_SIZE + data_size, 0)) < 0)
  164.         return ret;
  165.     out = avpkt->data;
  166.  
  167.     bytestream_put_byte(&out, stereo ? 0x21 : 0x20);
  168.     bytestream_put_byte(&out, 0x10);
  169.     bytestream_put_le32(&out, data_size);
  170.  
  171.     if (stereo) {
  172.         bytestream_put_byte(&out, (context->lastSample[1])>>8);
  173.         bytestream_put_byte(&out, (context->lastSample[0])>>8);
  174.     } else
  175.         bytestream_put_le16(&out, context->lastSample[0]);
  176.  
  177.     /* Write the actual samples */
  178.     for (i = 0; i < data_size; i++)
  179.         *out++ = dpcm_predict(&context->lastSample[i & 1], *in++);
  180.  
  181.     avpkt->pts      = context->input_frames <= 7 ? context->first_pts : frame->pts;
  182.     avpkt->duration = data_size / avctx->channels;
  183.  
  184.     context->input_frames++;
  185.     if (!in)
  186.         context->input_frames = FFMAX(context->input_frames, 8);
  187.  
  188.     *got_packet_ptr = 1;
  189.     return 0;
  190. }
  191.  
  192. AVCodec ff_roq_dpcm_encoder = {
  193.     .name           = "roq_dpcm",
  194.     .long_name      = NULL_IF_CONFIG_SMALL("id RoQ DPCM"),
  195.     .type           = AVMEDIA_TYPE_AUDIO,
  196.     .id             = AV_CODEC_ID_ROQ_DPCM,
  197.     .priv_data_size = sizeof(ROQDPCMContext),
  198.     .init           = roq_dpcm_encode_init,
  199.     .encode2        = roq_dpcm_encode_frame,
  200.     .close          = roq_dpcm_encode_close,
  201.     .capabilities   = AV_CODEC_CAP_DELAY,
  202.     .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
  203.                                                      AV_SAMPLE_FMT_NONE },
  204. };
  205.