diff options
Diffstat (limited to 'libavcodec/roqvideoenc.c')
-rw-r--r-- | libavcodec/roqvideoenc.c | 79 |
1 files changed, 45 insertions, 34 deletions
diff --git a/libavcodec/roqvideoenc.c b/libavcodec/roqvideoenc.c index af0089fb7f..cae157b768 100644 --- a/libavcodec/roqvideoenc.c +++ b/libavcodec/roqvideoenc.c @@ -5,27 +5,27 @@ * Copyright (C) 2004-2007 Eric Lasota * Based on RoQ specs (C) 2001 Tim Ferguson * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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.1 of the License, or (at your option) any later version. * - * Libav 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 Libav; 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 * id RoQ encoder by Vitor. Based on the Switchblade3 library and the - * Switchblade3 Libav glue by Eric Lasota. + * Switchblade3 FFmpeg glue by Eric Lasota. */ /* @@ -57,6 +57,7 @@ #include <string.h> #include "libavutil/attributes.h" +#include "libavutil/opt.h" #include "roqvideo.h" #include "bytestream.h" #include "elbg.h" @@ -69,7 +70,7 @@ * Maximum number of generated 4x4 codebooks. Can't be 256 to workaround a * Quake 3 bug. */ -#define MAX_CBS_4x4 255 +#define MAX_CBS_4x4 256 #define MAX_CBS_2x2 256 ///< Maximum number of 2x2 codebooks. @@ -248,7 +249,7 @@ static void create_cel_evals(RoqContext *enc, RoqTempdata *tempData) { int n=0, x, y, i; - tempData->cel_evals = av_malloc(enc->width*enc->height/64 * sizeof(CelEvaluation)); + tempData->cel_evals = av_malloc_array(enc->width*enc->height/64, sizeof(CelEvaluation)); /* Map to the ROQ quadtree order */ for (y=0; y<enc->height; y+=16) @@ -540,7 +541,7 @@ static void remap_codebooks(RoqContext *enc, RoqTempdata *tempData) int i, j, idx=0; /* Make remaps for the final codebook usage */ - for (i=0; i<MAX_CBS_4x4; i++) { + for (i=0; i<(enc->quake3_compat ? MAX_CBS_4x4-1 : MAX_CBS_4x4); i++) { if (tempData->codebooks.usedCB4[i]) { tempData->i2f4[i] = idx; tempData->f2i4[idx] = i; @@ -798,16 +799,16 @@ static void generate_codebook(RoqContext *enc, RoqTempdata *tempdata, int i, j, k; int c_size = size*size/4; int *buf; - int *codebook = av_malloc(6*c_size*cbsize*sizeof(int)); + int *codebook = av_malloc_array(6*c_size, cbsize*sizeof(int)); int *closest_cb; if (size == 4) - closest_cb = av_malloc(6*c_size*inputCount*sizeof(int)); + closest_cb = av_malloc_array(6*c_size, inputCount*sizeof(int)); else closest_cb = tempdata->closest_cb2; - ff_init_elbg(points, 6*c_size, inputCount, codebook, cbsize, 1, closest_cb, &enc->randctx); - ff_do_elbg(points, 6*c_size, inputCount, codebook, cbsize, 1, closest_cb, &enc->randctx); + avpriv_init_elbg(points, 6*c_size, inputCount, codebook, cbsize, 1, closest_cb, &enc->randctx); + avpriv_do_elbg(points, 6*c_size, inputCount, codebook, cbsize, 1, closest_cb, &enc->randctx); if (size == 4) av_free(closest_cb); @@ -833,8 +834,8 @@ static void generate_new_codebooks(RoqContext *enc, RoqTempdata *tempData) int max = enc->width*enc->height/16; uint8_t mb2[3*4]; roq_cell *results4 = av_malloc(sizeof(roq_cell)*MAX_CBS_4x4*4); - uint8_t *yuvClusters=av_malloc(sizeof(int)*max*6*4); - int *points = av_malloc(max*6*4*sizeof(int)); + uint8_t *yuvClusters=av_malloc_array(max, sizeof(int)*6*4); + int *points = av_malloc_array(max, 6*4*sizeof(int)); int bias; /* Subsample YUV data */ @@ -847,11 +848,11 @@ static void generate_new_codebooks(RoqContext *enc, RoqTempdata *tempData) } /* Create 4x4 codebooks */ - generate_codebook(enc, tempData, points, max, results4, 4, MAX_CBS_4x4); + generate_codebook(enc, tempData, points, max, results4, 4, (enc->quake3_compat ? MAX_CBS_4x4-1 : MAX_CBS_4x4)); - codebooks->numCB4 = MAX_CBS_4x4; + codebooks->numCB4 = (enc->quake3_compat ? MAX_CBS_4x4-1 : MAX_CBS_4x4); - tempData->closest_cb2 = av_malloc(max*4*sizeof(int)); + tempData->closest_cb2 = av_malloc_array(max, 4*sizeof(int)); /* Create 2x2 codebooks */ generate_codebook(enc, tempData, points, max*4, enc->cb2x2, 2, MAX_CBS_2x2); @@ -901,10 +902,10 @@ static void roq_encode_video(RoqContext *enc) gather_data_for_cel(tempData->cel_evals + i, enc, tempData); /* Quake 3 can't handle chunks bigger than 65535 bytes */ - if (tempData->mainChunkSize/8 > 65535) { + if (tempData->mainChunkSize/8 > 65535 && enc->quake3_compat) { av_log(enc->avctx, AV_LOG_ERROR, - "Warning, generated a frame too big (%d > 65535), " - "try using a smaller qscale value.\n", + "Warning, generated a frame too big for Quake (%d > 65535), " + "now switching to a bigger qscale value.\n", tempData->mainChunkSize/8); enc->lambda *= 1.5; tempData->mainChunkSize = 0; @@ -962,7 +963,7 @@ static av_cold int roq_encode_init(AVCodecContext *avctx) enc->framesSinceKeyframe = 0; if ((avctx->width & 0xf) || (avctx->height & 0xf)) { av_log(avctx, AV_LOG_ERROR, "Dimensions must be divisible by 16\n"); - return -1; + return AVERROR(EINVAL); } if (((avctx->width)&(avctx->width-1))||((avctx->height)&(avctx->height-1))) @@ -984,16 +985,16 @@ static av_cold int roq_encode_init(AVCodecContext *avctx) enc->tmpData = av_malloc(sizeof(RoqTempdata)); enc->this_motion4 = - av_mallocz((enc->width*enc->height/16)*sizeof(motion_vect)); + av_mallocz_array((enc->width*enc->height/16), sizeof(motion_vect)); enc->last_motion4 = - av_malloc ((enc->width*enc->height/16)*sizeof(motion_vect)); + av_malloc_array ((enc->width*enc->height/16), sizeof(motion_vect)); enc->this_motion8 = - av_mallocz((enc->width*enc->height/64)*sizeof(motion_vect)); + av_mallocz_array((enc->width*enc->height/64), sizeof(motion_vect)); enc->last_motion8 = - av_malloc ((enc->width*enc->height/64)*sizeof(motion_vect)); + av_malloc_array ((enc->width*enc->height/64), sizeof(motion_vect)); return 0; } @@ -1041,10 +1042,8 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt, /* 138 bits max per 8x8 block + * 256 codebooks*(6 bytes 2x2 + 4 bytes 4x4) + 8 bytes frame header */ size = ((enc->width * enc->height / 64) * 138 + 7) / 8 + 256 * (6 + 4) + 8; - if ((ret = ff_alloc_packet(pkt, size)) < 0) { - av_log(avctx, AV_LOG_ERROR, "Error getting output packet with size %d.\n", size); + if ((ret = ff_alloc_packet2(avctx, pkt, size)) < 0) return ret; - } enc->out_buf = pkt->data; /* Check for I frame */ @@ -1054,11 +1053,9 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt, if (enc->first_frame) { /* Alloc memory for the reconstruction data (we must know the stride for that) */ - if (ff_get_buffer(avctx, enc->current_frame, 0) || - ff_get_buffer(avctx, enc->last_frame, 0)) { - av_log(avctx, AV_LOG_ERROR, " RoQ: get_buffer() failed\n"); - return -1; - } + if ((ret = ff_get_buffer(avctx, enc->current_frame, 0)) < 0 || + (ret = ff_get_buffer(avctx, enc->last_frame, 0)) < 0) + return ret; /* Before the first video frame, write a "video info" chunk */ roq_write_video_info_chunk(enc); @@ -1077,6 +1074,20 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } +#define OFFSET(x) offsetof(RoqContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "quake3_compat", "Whether to respect known limitations in Quake 3 decoder", OFFSET(quake3_compat), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE }, + { NULL }, +}; + +static const AVClass roq_class = { + .class_name = "RoQ", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVCodec ff_roq_encoder = { .name = "roqvideo", .long_name = NULL_IF_CONFIG_SMALL("id RoQ video"), @@ -1086,7 +1097,7 @@ AVCodec ff_roq_encoder = { .init = roq_encode_init, .encode2 = roq_encode_frame, .close = roq_encode_end, - .supported_framerates = (const AVRational[]){ {30,1}, {0,0} }, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }, + .priv_class = &roq_class, }; |