Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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
  36. {
  37.     short lastSample[2];
  38.     int input_frames;
  39.     int buffered_samples;
  40.     int16_t *frame_buffer;
  41.     int64_t first_pts;
  42. } ROQDPCMContext;
  43.  
  44.  
  45. static av_cold int roq_dpcm_encode_close(AVCodecContext *avctx)
  46. {
  47.     ROQDPCMContext *context = avctx->priv_data;
  48.  
  49.     av_freep(&context->frame_buffer);
  50.  
  51.     return 0;
  52. }
  53.  
  54. static av_cold int roq_dpcm_encode_init(AVCodecContext *avctx)
  55. {
  56.     ROQDPCMContext *context = avctx->priv_data;
  57.     int ret;
  58.  
  59.     if (avctx->channels > 2) {
  60.         av_log(avctx, AV_LOG_ERROR, "Audio must be mono or stereo\n");
  61.         return AVERROR(EINVAL);
  62.     }
  63.     if (avctx->sample_rate != 22050) {
  64.         av_log(avctx, AV_LOG_ERROR, "Audio must be 22050 Hz\n");
  65.         return AVERROR(EINVAL);
  66.     }
  67.  
  68.     avctx->frame_size = ROQ_FRAME_SIZE;
  69.     avctx->bit_rate   = (ROQ_HEADER_SIZE + ROQ_FRAME_SIZE * avctx->channels) *
  70.                         (22050 / ROQ_FRAME_SIZE) * 8;
  71.  
  72.     context->frame_buffer = av_malloc(8 * ROQ_FRAME_SIZE * avctx->channels *
  73.                                       sizeof(*context->frame_buffer));
  74.     if (!context->frame_buffer) {
  75.         ret = AVERROR(ENOMEM);
  76.         goto error;
  77.     }
  78.  
  79.     context->lastSample[0] = context->lastSample[1] = 0;
  80.  
  81.     return 0;
  82. error:
  83.     roq_dpcm_encode_close(avctx);
  84.     return ret;
  85. }
  86.  
  87. static unsigned char dpcm_predict(short *previous, short current)
  88. {
  89.     int diff;
  90.     int negative;
  91.     int result;
  92.     int predicted;
  93.  
  94.     diff = current - *previous;
  95.  
  96.     negative = diff<0;
  97.     diff = FFABS(diff);
  98.  
  99.     if (diff >= MAX_DPCM)
  100.         result = 127;
  101.     else {
  102.         result = ff_sqrt(diff);
  103.         result += diff > result*result+result;
  104.     }
  105.  
  106.     /* See if this overflows */
  107.  retry:
  108.     diff = result*result;
  109.     if (negative)
  110.         diff = -diff;
  111.     predicted = *previous + diff;
  112.  
  113.     /* If it overflows, back off a step */
  114.     if (predicted > 32767 || predicted < -32768) {
  115.         result--;
  116.         goto retry;
  117.     }
  118.  
  119.     /* Add the sign bit */
  120.     result |= negative << 7;   //if (negative) result |= 128;
  121.  
  122.     *previous = predicted;
  123.  
  124.     return result;
  125. }
  126.  
  127. static int roq_dpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
  128.                                  const AVFrame *frame, int *got_packet_ptr)
  129. {
  130.     int i, stereo, data_size, ret;
  131.     const int16_t *in = frame ? (const int16_t *)frame->data[0] : NULL;
  132.     uint8_t *out;
  133.     ROQDPCMContext *context = avctx->priv_data;
  134.  
  135.     stereo = (avctx->channels == 2);
  136.  
  137.     if (!in && context->input_frames >= 8)
  138.         return 0;
  139.  
  140.     if (in && context->input_frames < 8) {
  141.         memcpy(&context->frame_buffer[context->buffered_samples * avctx->channels],
  142.                in, avctx->frame_size * avctx->channels * sizeof(*in));
  143.         context->buffered_samples += avctx->frame_size;
  144.         if (context->input_frames == 0)
  145.             context->first_pts = frame->pts;
  146.         if (context->input_frames < 7) {
  147.             context->input_frames++;
  148.             return 0;
  149.         }
  150.     }
  151.     if (context->input_frames < 8) {
  152.         in = context->frame_buffer;
  153.     }
  154.  
  155.     if (stereo) {
  156.         context->lastSample[0] &= 0xFF00;
  157.         context->lastSample[1] &= 0xFF00;
  158.     }
  159.  
  160.     if (context->input_frames == 7)
  161.         data_size = avctx->channels * context->buffered_samples;
  162.     else
  163.         data_size = avctx->channels * avctx->frame_size;
  164.  
  165.     if ((ret = ff_alloc_packet2(avctx, avpkt, ROQ_HEADER_SIZE + data_size)) < 0)
  166.         return ret;
  167.     out = avpkt->data;
  168.  
  169.     bytestream_put_byte(&out, stereo ? 0x21 : 0x20);
  170.     bytestream_put_byte(&out, 0x10);
  171.     bytestream_put_le32(&out, data_size);
  172.  
  173.     if (stereo) {
  174.         bytestream_put_byte(&out, (context->lastSample[1])>>8);
  175.         bytestream_put_byte(&out, (context->lastSample[0])>>8);
  176.     } else
  177.         bytestream_put_le16(&out, context->lastSample[0]);
  178.  
  179.     /* Write the actual samples */
  180.     for (i = 0; i < data_size; i++)
  181.         *out++ = dpcm_predict(&context->lastSample[i & 1], *in++);
  182.  
  183.     avpkt->pts      = context->input_frames <= 7 ? context->first_pts : frame->pts;
  184.     avpkt->duration = data_size / avctx->channels;
  185.  
  186.     context->input_frames++;
  187.     if (!in)
  188.         context->input_frames = FFMAX(context->input_frames, 8);
  189.  
  190.     *got_packet_ptr = 1;
  191.     return 0;
  192. }
  193.  
  194. AVCodec ff_roq_dpcm_encoder = {
  195.     .name           = "roq_dpcm",
  196.     .long_name      = NULL_IF_CONFIG_SMALL("id RoQ DPCM"),
  197.     .type           = AVMEDIA_TYPE_AUDIO,
  198.     .id             = AV_CODEC_ID_ROQ_DPCM,
  199.     .priv_data_size = sizeof(ROQDPCMContext),
  200.     .init           = roq_dpcm_encode_init,
  201.     .encode2        = roq_dpcm_encode_frame,
  202.     .close          = roq_dpcm_encode_close,
  203.     .capabilities   = CODEC_CAP_DELAY,
  204.     .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
  205.                                                      AV_SAMPLE_FMT_NONE },
  206. };
  207.