annotate ffmpeg/libavcodec/roqaudioenc.c @ 13:844d341cf643 tip

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