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 #include "internal.h"
00028
00029 #define ROQ_FRAME_SIZE 735
00030 #define ROQ_HEADER_SIZE 8
00031
00032 #define MAX_DPCM (127*127)
00033
00034
00035 typedef struct
00036 {
00037 short lastSample[2];
00038 int input_frames;
00039 int buffered_samples;
00040 int16_t *frame_buffer;
00041 int64_t first_pts;
00042 } ROQDPCMContext;
00043
00044
00045 static av_cold int roq_dpcm_encode_close(AVCodecContext *avctx)
00046 {
00047 ROQDPCMContext *context = avctx->priv_data;
00048
00049 #if FF_API_OLD_ENCODE_AUDIO
00050 av_freep(&avctx->coded_frame);
00051 #endif
00052 av_freep(&context->frame_buffer);
00053
00054 return 0;
00055 }
00056
00057 static av_cold int roq_dpcm_encode_init(AVCodecContext *avctx)
00058 {
00059 ROQDPCMContext *context = avctx->priv_data;
00060 int ret;
00061
00062 if (avctx->channels > 2) {
00063 av_log(avctx, AV_LOG_ERROR, "Audio must be mono or stereo\n");
00064 return AVERROR(EINVAL);
00065 }
00066 if (avctx->sample_rate != 22050) {
00067 av_log(avctx, AV_LOG_ERROR, "Audio must be 22050 Hz\n");
00068 return AVERROR(EINVAL);
00069 }
00070
00071 avctx->frame_size = ROQ_FRAME_SIZE;
00072 avctx->bit_rate = (ROQ_HEADER_SIZE + ROQ_FRAME_SIZE * avctx->channels) *
00073 (22050 / ROQ_FRAME_SIZE) * 8;
00074
00075 context->frame_buffer = av_malloc(8 * ROQ_FRAME_SIZE * avctx->channels *
00076 sizeof(*context->frame_buffer));
00077 if (!context->frame_buffer) {
00078 ret = AVERROR(ENOMEM);
00079 goto error;
00080 }
00081
00082 context->lastSample[0] = context->lastSample[1] = 0;
00083
00084 #if FF_API_OLD_ENCODE_AUDIO
00085 avctx->coded_frame= avcodec_alloc_frame();
00086 if (!avctx->coded_frame) {
00087 ret = AVERROR(ENOMEM);
00088 goto error;
00089 }
00090 #endif
00091
00092 return 0;
00093 error:
00094 roq_dpcm_encode_close(avctx);
00095 return ret;
00096 }
00097
00098 static unsigned char dpcm_predict(short *previous, short current)
00099 {
00100 int diff;
00101 int negative;
00102 int result;
00103 int predicted;
00104
00105 diff = current - *previous;
00106
00107 negative = diff<0;
00108 diff = FFABS(diff);
00109
00110 if (diff >= MAX_DPCM)
00111 result = 127;
00112 else {
00113 result = ff_sqrt(diff);
00114 result += diff > result*result+result;
00115 }
00116
00117
00118 retry:
00119 diff = result*result;
00120 if (negative)
00121 diff = -diff;
00122 predicted = *previous + diff;
00123
00124
00125 if (predicted > 32767 || predicted < -32768) {
00126 result--;
00127 goto retry;
00128 }
00129
00130
00131 result |= negative << 7;
00132
00133 *previous = predicted;
00134
00135 return result;
00136 }
00137
00138 static int roq_dpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
00139 const AVFrame *frame, int *got_packet_ptr)
00140 {
00141 int i, stereo, data_size, ret;
00142 const int16_t *in = frame ? (const int16_t *)frame->data[0] : NULL;
00143 uint8_t *out;
00144 ROQDPCMContext *context = avctx->priv_data;
00145
00146 stereo = (avctx->channels == 2);
00147
00148 if (!in && context->input_frames >= 8)
00149 return 0;
00150
00151 if (in && context->input_frames < 8) {
00152 memcpy(&context->frame_buffer[context->buffered_samples * avctx->channels],
00153 in, avctx->frame_size * avctx->channels * sizeof(*in));
00154 context->buffered_samples += avctx->frame_size;
00155 if (context->input_frames == 0)
00156 context->first_pts = frame->pts;
00157 if (context->input_frames < 7) {
00158 context->input_frames++;
00159 return 0;
00160 }
00161 in = context->frame_buffer;
00162 }
00163
00164 if (stereo) {
00165 context->lastSample[0] &= 0xFF00;
00166 context->lastSample[1] &= 0xFF00;
00167 }
00168
00169 if (context->input_frames == 7 || !in)
00170 data_size = avctx->channels * context->buffered_samples;
00171 else
00172 data_size = avctx->channels * avctx->frame_size;
00173
00174 if ((ret = ff_alloc_packet2(avctx, avpkt, ROQ_HEADER_SIZE + data_size)))
00175 return ret;
00176 out = avpkt->data;
00177
00178 bytestream_put_byte(&out, stereo ? 0x21 : 0x20);
00179 bytestream_put_byte(&out, 0x10);
00180 bytestream_put_le32(&out, data_size);
00181
00182 if (stereo) {
00183 bytestream_put_byte(&out, (context->lastSample[1])>>8);
00184 bytestream_put_byte(&out, (context->lastSample[0])>>8);
00185 } else
00186 bytestream_put_le16(&out, context->lastSample[0]);
00187
00188
00189 for (i = 0; i < data_size; i++)
00190 *out++ = dpcm_predict(&context->lastSample[i & 1], *in++);
00191
00192 avpkt->pts = context->input_frames <= 7 ? context->first_pts : frame->pts;
00193 avpkt->duration = data_size / avctx->channels;
00194
00195 context->input_frames++;
00196 if (!in)
00197 context->input_frames = FFMAX(context->input_frames, 8);
00198
00199 *got_packet_ptr = 1;
00200 return 0;
00201 }
00202
00203 AVCodec ff_roq_dpcm_encoder = {
00204 .name = "roq_dpcm",
00205 .type = AVMEDIA_TYPE_AUDIO,
00206 .id = CODEC_ID_ROQ_DPCM,
00207 .priv_data_size = sizeof(ROQDPCMContext),
00208 .init = roq_dpcm_encode_init,
00209 .encode2 = roq_dpcm_encode_frame,
00210 .close = roq_dpcm_encode_close,
00211 .capabilities = CODEC_CAP_DELAY,
00212 .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
00213 AV_SAMPLE_FMT_NONE },
00214 .long_name = NULL_IF_CONFIG_SMALL("id RoQ DPCM"),
00215 };