* Duck/ON2 TrueMotion 2 Decoder
* Copyright (c) 2005 Konstantin Shishkov
*
- * This library is free software; you can redistribute it and/or
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
- * This library is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
*/
/**
- * @file truemotion2.c
+ * @file libavcodec/truemotion2.c
* Duck TrueMotion2 decoder.
*/
#include "avcodec.h"
-#include "common.h"
#include "bitstream.h"
#include "dsputil.h"
return code->recode[val];
}
-static inline int tm2_read_header(TM2Context *ctx, uint8_t *buf)
+static inline int tm2_read_header(TM2Context *ctx, const uint8_t *buf)
{
uint32_t magic;
- uint8_t *obuf;
+ const uint8_t *obuf;
int length;
obuf = buf;
- magic = LE_32(buf);
+ magic = AV_RL32(buf);
buf += 4;
if(magic == 0x00000100) { /* old header */
} else if(magic == 0x00000101) { /* new header */
int w, h, size, flags, xr, yr;
- length = LE_32(buf);
+ length = AV_RL32(buf);
buf += 4;
init_get_bits(&ctx->gb, buf, 32 * 8);
return -1;
}
- return (buf - obuf);
+ return buf - obuf;
}
static int tm2_read_deltas(TM2Context *ctx, int stream_id) {
return 0;
}
-static int tm2_read_stream(TM2Context *ctx, uint8_t *buf, int stream_id) {
+static int tm2_read_stream(TM2Context *ctx, const uint8_t *buf, int stream_id) {
int i;
int cur = 0;
int skip = 0;
TM2Codes codes;
/* get stream length in dwords */
- len = BE_32(buf); buf += 4; cur += 4;
+ len = AV_RB32(buf); buf += 4; cur += 4;
skip = len * 4 + 4;
if(len == 0)
return 4;
- toks = BE_32(buf); buf += 4; cur += 4;
+ toks = AV_RB32(buf); buf += 4; cur += 4;
if(toks & 1) {
- len = BE_32(buf); buf += 4; cur += 4;
+ len = AV_RB32(buf); buf += 4; cur += 4;
if(len == TM2_ESCAPE) {
- len = BE_32(buf); buf += 4; cur += 4;
+ len = AV_RB32(buf); buf += 4; cur += 4;
}
if(len > 0) {
init_get_bits(&ctx->gb, buf, (skip - cur) * 8);
}
}
/* skip unused fields */
- if(BE_32(buf) == TM2_ESCAPE) {
+ if(AV_RB32(buf) == TM2_ESCAPE) {
buf += 4; cur += 4; /* some unknown length - could be escaped too */
}
buf += 4; cur += 4;
}
ctx->tokens[stream_id] = av_realloc(ctx->tokens[stream_id], toks * sizeof(int));
ctx->tok_lens[stream_id] = toks;
- len = BE_32(buf); buf += 4; cur += 4;
+ len = AV_RB32(buf); buf += 4; cur += 4;
if(len > 0) {
init_get_bits(&ctx->gb, buf, (skip - cur) * 8);
for(i = 0; i < toks; i++)
d = deltas[i + j * 4];
ct += d;
last[i] += ct;
- Y[i] = clip_uint8(last[i]);
+ Y[i] = av_clip_uint8(last[i]);
}
Y += stride;
ctx->D[j] = ct;
src = (ctx->cur?ctx->Y2:ctx->Y1);
for(j = 0; j < ctx->avctx->height; j++){
for(i = 0; i < ctx->avctx->width; i++){
- Y[i] = clip_uint8(*src++);
+ Y[i] = av_clip_uint8(*src++);
}
Y += p->linesize[0];
}
src = (ctx->cur?ctx->U2:ctx->U1);
for(j = 0; j < (ctx->avctx->height + 1) >> 1; j++){
for(i = 0; i < (ctx->avctx->width + 1) >> 1; i++){
- U[i] = clip_uint8(*src++);
+ U[i] = av_clip_uint8(*src++);
}
U += p->linesize[2];
}
src = (ctx->cur?ctx->V2:ctx->V1);
for(j = 0; j < (ctx->avctx->height + 1) >> 1; j++){
for(i = 0; i < (ctx->avctx->width + 1) >> 1; i++){
- V[i] = clip_uint8(*src++);
+ V[i] = av_clip_uint8(*src++);
}
V += p->linesize[1];
}
return keyframe;
}
+static const int tm2_stream_order[TM2_NUM_STREAMS] = {
+ TM2_C_HI, TM2_C_LO, TM2_L_HI, TM2_L_LO, TM2_UPD, TM2_MOT, TM2_TYPE
+};
+
static int decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
- uint8_t *buf, int buf_size)
+ const uint8_t *buf, int buf_size)
{
TM2Context * const l = avctx->priv_data;
AVFrame * const p= (AVFrame*)&l->pic;
- int skip, t;
+ int i, skip, t;
+ uint8_t *swbuf;
+ swbuf = av_malloc(buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ if(!swbuf){
+ av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n");
+ return -1;
+ }
p->reference = 1;
p->buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
if(avctx->reget_buffer(avctx, p) < 0){
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ av_free(swbuf);
return -1;
}
- l->dsp.bswap_buf((uint32_t*)buf, (uint32_t*)buf, buf_size >> 2);
- skip = tm2_read_header(l, buf);
+ l->dsp.bswap_buf((uint32_t*)swbuf, (const uint32_t*)buf, buf_size >> 2);
+ skip = tm2_read_header(l, swbuf);
- if(skip == -1)
+ if(skip == -1){
+ av_free(swbuf);
return -1;
+ }
- t = tm2_read_stream(l, buf + skip, TM2_C_HI);
- if(t == -1)
- return -1;
- skip += t;
- t = tm2_read_stream(l, buf + skip, TM2_C_LO);
- if(t == -1)
- return -1;
- skip += t;
- t = tm2_read_stream(l, buf + skip, TM2_L_HI);
- if(t == -1)
- return -1;
- skip += t;
- t = tm2_read_stream(l, buf + skip, TM2_L_LO);
- if(t == -1)
- return -1;
- skip += t;
- t = tm2_read_stream(l, buf + skip, TM2_UPD);
- if(t == -1)
- return -1;
- skip += t;
- t = tm2_read_stream(l, buf + skip, TM2_MOT);
- if(t == -1)
- return -1;
- skip += t;
- t = tm2_read_stream(l, buf + skip, TM2_TYPE);
- if(t == -1)
- return -1;
+ for(i = 0; i < TM2_NUM_STREAMS; i++){
+ t = tm2_read_stream(l, swbuf + skip, tm2_stream_order[i]);
+ if(t == -1){
+ av_free(swbuf);
+ return -1;
+ }
+ skip += t;
+ }
p->key_frame = tm2_decode_blocks(l, p);
if(p->key_frame)
p->pict_type = FF_I_TYPE;
l->cur = !l->cur;
*data_size = sizeof(AVFrame);
*(AVFrame*)data = l->pic;
+ av_free(swbuf);
return buf_size;
}
-static int decode_init(AVCodecContext *avctx){
+static av_cold int decode_init(AVCodecContext *avctx){
TM2Context * const l = avctx->priv_data;
int i;
- if (avcodec_check_dimensions(avctx, avctx->height, avctx->width) < 0) {
+ if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
return -1;
}
if((avctx->width & 3) || (avctx->height & 3)){
l->avctx = avctx;
l->pic.data[0]=NULL;
- avctx->has_b_frames = 0;
avctx->pix_fmt = PIX_FMT_YUV420P;
dsputil_init(&l->dsp, avctx);
return 0;
}
-static int decode_end(AVCodecContext *avctx){
+static av_cold int decode_end(AVCodecContext *avctx){
TM2Context * const l = avctx->priv_data;
int i;
decode_end,
decode_frame,
CODEC_CAP_DR1,
+ .long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0"),
};