00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "libavutil/intmath.h"
00025 #include "avcodec.h"
00026 #include "bytestream.h"
00027
00028 #define ROQ_FIRST_FRAME_SIZE (735*8)
00029 #define ROQ_FRAME_SIZE 735
00030
00031
00032 #define MAX_DPCM (127*127)
00033
00034
00035 typedef struct
00036 {
00037 short lastSample[2];
00038 } ROQDPCMContext;
00039
00040 static av_cold int roq_dpcm_encode_init(AVCodecContext *avctx)
00041 {
00042 ROQDPCMContext *context = avctx->priv_data;
00043
00044 if (avctx->channels > 2) {
00045 av_log(avctx, AV_LOG_ERROR, "Audio must be mono or stereo\n");
00046 return -1;
00047 }
00048 if (avctx->sample_rate != 22050) {
00049 av_log(avctx, AV_LOG_ERROR, "Audio must be 22050 Hz\n");
00050 return -1;
00051 }
00052 if (avctx->sample_fmt != AV_SAMPLE_FMT_S16) {
00053 av_log(avctx, AV_LOG_ERROR, "Audio must be signed 16-bit\n");
00054 return -1;
00055 }
00056
00057 avctx->frame_size = ROQ_FIRST_FRAME_SIZE;
00058
00059 context->lastSample[0] = context->lastSample[1] = 0;
00060
00061 avctx->coded_frame= avcodec_alloc_frame();
00062 avctx->coded_frame->key_frame= 1;
00063
00064 return 0;
00065 }
00066
00067 static unsigned char dpcm_predict(short *previous, short current)
00068 {
00069 int diff;
00070 int negative;
00071 int result;
00072 int predicted;
00073
00074 diff = current - *previous;
00075
00076 negative = diff<0;
00077 diff = FFABS(diff);
00078
00079 if (diff >= MAX_DPCM)
00080 result = 127;
00081 else {
00082 result = ff_sqrt(diff);
00083 result += diff > result*result+result;
00084 }
00085
00086
00087 retry:
00088 diff = result*result;
00089 if (negative)
00090 diff = -diff;
00091 predicted = *previous + diff;
00092
00093
00094 if (predicted > 32767 || predicted < -32768) {
00095 result--;
00096 goto retry;
00097 }
00098
00099
00100 result |= negative << 7;
00101
00102 *previous = predicted;
00103
00104 return result;
00105 }
00106
00107 static int roq_dpcm_encode_frame(AVCodecContext *avctx,
00108 unsigned char *frame, int buf_size, void *data)
00109 {
00110 int i, samples, stereo, ch;
00111 const short *in;
00112 unsigned char *out;
00113
00114 ROQDPCMContext *context = avctx->priv_data;
00115
00116 stereo = (avctx->channels == 2);
00117
00118 if (stereo) {
00119 context->lastSample[0] &= 0xFF00;
00120 context->lastSample[1] &= 0xFF00;
00121 }
00122
00123 out = frame;
00124 in = data;
00125
00126 bytestream_put_byte(&out, stereo ? 0x21 : 0x20);
00127 bytestream_put_byte(&out, 0x10);
00128 bytestream_put_le32(&out, avctx->frame_size*avctx->channels);
00129
00130 if (stereo) {
00131 bytestream_put_byte(&out, (context->lastSample[1])>>8);
00132 bytestream_put_byte(&out, (context->lastSample[0])>>8);
00133 } else
00134 bytestream_put_le16(&out, context->lastSample[0]);
00135
00136
00137 samples = avctx->frame_size;
00138 for (i=0; i<samples; i++)
00139 for (ch=0; ch<avctx->channels; ch++)
00140 *out++ = dpcm_predict(&context->lastSample[ch], *in++);
00141
00142
00143 avctx->frame_size = ROQ_FRAME_SIZE;
00144
00145
00146 return out - frame;
00147 }
00148
00149 static av_cold int roq_dpcm_encode_close(AVCodecContext *avctx)
00150 {
00151 av_freep(&avctx->coded_frame);
00152
00153 return 0;
00154 }
00155
00156 AVCodec ff_roq_dpcm_encoder = {
00157 "roq_dpcm",
00158 AVMEDIA_TYPE_AUDIO,
00159 CODEC_ID_ROQ_DPCM,
00160 sizeof(ROQDPCMContext),
00161 roq_dpcm_encode_init,
00162 roq_dpcm_encode_frame,
00163 roq_dpcm_encode_close,
00164 NULL,
00165 .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE},
00166 .long_name = NULL_IF_CONFIG_SMALL("id RoQ DPCM"),
00167 };