diff options
Diffstat (limited to 'libavcodec/a64multienc.c')
-rw-r--r-- | libavcodec/a64multienc.c | 97 |
1 files changed, 56 insertions, 41 deletions
diff --git a/libavcodec/a64multienc.c b/libavcodec/a64multienc.c index d742dee..f9c4f36 100644 --- a/libavcodec/a64multienc.c +++ b/libavcodec/a64multienc.c @@ -2,20 +2,20 @@ * a64 video encoder - multicolor modes * Copyright (c) 2009 Tobias Bindhammer * - * 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 */ @@ -24,11 +24,11 @@ * a64 video encoder - multicolor modes */ -#include "a64enc.h" #include "a64colors.h" #include "a64tables.h" #include "elbg.h" #include "internal.h" +#include "libavutil/avassert.h" #include "libavutil/common.h" #include "libavutil/intreadwrite.h" @@ -37,6 +37,28 @@ #define INTERLACED 1 #define CROP_SCREENS 1 +#define C64XRES 320 +#define C64YRES 200 + +typedef struct A64Context { + /* variables for multicolor modes */ + AVLFG randctx; + int mc_lifetime; + int mc_use_5col; + unsigned mc_frame_counter; + int *mc_meta_charset; + int *mc_charmap; + int *mc_best_cb; + int mc_luma_vals[5]; + uint8_t *mc_charset; + uint8_t *mc_colram; + uint8_t *mc_palette; + int mc_pal_size; + + /* pts of the next packet that will be output */ + int64_t next_pts; +} A64Context; + /* gray gradient */ static const int mc_colors[5]={0x0,0xb,0xc,0xf,0x1}; @@ -44,7 +66,7 @@ static const int mc_colors[5]={0x0,0xb,0xc,0xf,0x1}; //static const int mc_colors[5]={0x0,0x8,0xa,0xf,0x7}; //static const int mc_colors[5]={0x0,0x9,0x8,0xa,0x3}; -static void to_meta_with_crop(AVCodecContext *avctx, AVFrame *p, int *dest) +static void to_meta_with_crop(AVCodecContext *avctx, const AVFrame *p, int *dest) { int blockx, blocky, x, y; int luma = 0; @@ -57,9 +79,13 @@ static void to_meta_with_crop(AVCodecContext *avctx, AVFrame *p, int *dest) for (y = blocky; y < blocky + 8 && y < C64YRES; y++) { for (x = blockx; x < blockx + 8 && x < C64XRES; x += 2) { if(x < width && y < height) { - /* build average over 2 pixels */ - luma = (src[(x + 0 + y * p->linesize[0])] + - src[(x + 1 + y * p->linesize[0])]) / 2; + if (x + 1 < width) { + /* build average over 2 pixels */ + luma = (src[(x + 0 + y * p->linesize[0])] + + src[(x + 1 + y * p->linesize[0])]) / 2; + } else { + luma = src[(x + y * p->linesize[0])]; + } /* write blocks as linear data now so they are suitable for elbg */ dest[0] = luma; } @@ -165,12 +191,11 @@ static void render_charset(AVCodecContext *avctx, uint8_t *charset, static av_cold int a64multi_close_encoder(AVCodecContext *avctx) { A64Context *c = avctx->priv_data; - av_frame_free(&avctx->coded_frame); - av_free(c->mc_meta_charset); - av_free(c->mc_best_cb); - av_free(c->mc_charset); - av_free(c->mc_charmap); - av_free(c->mc_colram); + av_freep(&c->mc_meta_charset); + av_freep(&c->mc_best_cb); + av_freep(&c->mc_charset); + av_freep(&c->mc_charmap); + av_freep(&c->mc_colram); return 0; } @@ -199,9 +224,9 @@ static av_cold int a64multi_encode_init(AVCodecContext *avctx) a64_palette[mc_colors[a]][2] * 0.11; } - if (!(c->mc_meta_charset = av_malloc(32000 * c->mc_lifetime * sizeof(int))) || + if (!(c->mc_meta_charset = av_mallocz_array(c->mc_lifetime, 32000 * sizeof(int))) || !(c->mc_best_cb = av_malloc(CHARSET_CHARS * 32 * sizeof(int))) || - !(c->mc_charmap = av_mallocz(1000 * c->mc_lifetime * sizeof(int))) || + !(c->mc_charmap = av_mallocz_array(c->mc_lifetime, 1000 * sizeof(int))) || !(c->mc_colram = av_mallocz(CHARSET_CHARS * sizeof(uint8_t))) || !(c->mc_charset = av_malloc(0x800 * (INTERLACED+1) * sizeof(uint8_t)))) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate buffer memory.\n"); @@ -217,14 +242,6 @@ static av_cold int a64multi_encode_init(AVCodecContext *avctx) AV_WB32(avctx->extradata, c->mc_lifetime); AV_WB32(avctx->extradata + 16, INTERLACED); - avctx->coded_frame = av_frame_alloc(); - if (!avctx->coded_frame) { - a64multi_close_encoder(avctx); - return AVERROR(ENOMEM); - } - - avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; - avctx->coded_frame->key_frame = 1; if (!avctx->codec_tag) avctx->codec_tag = AV_RL32("a64m"); @@ -249,10 +266,9 @@ static void a64_compress_colram(unsigned char *buf, int *charmap, uint8_t *colra } static int a64multi_encode_frame(AVCodecContext *avctx, AVPacket *pkt, - const AVFrame *pict, int *got_packet) + const AVFrame *p, int *got_packet) { A64Context *c = avctx->priv_data; - AVFrame *const p = avctx->coded_frame; int frame; int x, y; @@ -260,7 +276,7 @@ static int a64multi_encode_frame(AVCodecContext *avctx, AVPacket *pkt, int b_width; int req_size, ret; - uint8_t *buf; + uint8_t *buf = NULL; int *charmap = c->mc_charmap; uint8_t *colram = c->mc_colram; @@ -283,7 +299,7 @@ static int a64multi_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } /* no data, means end encoding asap */ - if (!pict) { + if (!p) { /* all done, end encoding */ if (!c->mc_lifetime) return 0; /* no more frames in queue, prepare to flush remaining frames */ @@ -296,13 +312,10 @@ static int a64multi_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } else { /* fill up mc_meta_charset with data until lifetime exceeds */ if (c->mc_frame_counter < c->mc_lifetime) { - *p = *pict; - p->pict_type = AV_PICTURE_TYPE_I; - p->key_frame = 1; to_meta_with_crop(avctx, p, meta + 32000 * c->mc_frame_counter); c->mc_frame_counter++; if (c->next_pts == AV_NOPTS_VALUE) - c->next_pts = pict->pts; + c->next_pts = p->pts; /* lifetime is not reached so wait for next frame first */ return 0; } @@ -313,19 +326,17 @@ static int a64multi_encode_frame(AVCodecContext *avctx, AVPacket *pkt, req_size = 0; /* any frames to encode? */ if (c->mc_lifetime) { - req_size = charset_size + c->mc_lifetime*(screen_size + colram_size); - if ((ret = ff_alloc_packet(pkt, req_size)) < 0) { - av_log(avctx, AV_LOG_ERROR, "Error getting output packet of size %d.\n", req_size); + int alloc_size = charset_size + c->mc_lifetime*(screen_size + colram_size); + if ((ret = ff_alloc_packet2(avctx, pkt, alloc_size)) < 0) return ret; - } buf = pkt->data; /* calc optimal new charset + charmaps */ - ret = ff_init_elbg(meta, 32, 1000 * c->mc_lifetime, best_cb, + ret = avpriv_init_elbg(meta, 32, 1000 * c->mc_lifetime, best_cb, CHARSET_CHARS, 50, charmap, &c->randctx); if (ret < 0) return ret; - ret = ff_do_elbg(meta, 32, 1000 * c->mc_lifetime, best_cb, + ret = avpriv_do_elbg(meta, 32, 1000 * c->mc_lifetime, best_cb, CHARSET_CHARS, 50, charmap, &c->randctx); if (ret < 0) return ret; @@ -338,7 +349,7 @@ static int a64multi_encode_frame(AVCodecContext *avctx, AVPacket *pkt, /* advance pointers */ buf += charset_size; - charset += charset_size; + req_size += charset_size; } /* write x frames to buf */ @@ -375,6 +386,7 @@ static int a64multi_encode_frame(AVCodecContext *avctx, AVPacket *pkt, pkt->pts = pkt->dts = c->next_pts; c->next_pts = AV_NOPTS_VALUE; + av_assert0(pkt->size >= req_size); pkt->size = req_size; pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = !!req_size; @@ -382,6 +394,7 @@ static int a64multi_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } +#if CONFIG_A64MULTI_ENCODER AVCodec ff_a64multi_encoder = { .name = "a64multi", .long_name = NULL_IF_CONFIG_SMALL("Multicolor charset for Commodore 64"), @@ -394,7 +407,8 @@ AVCodec ff_a64multi_encoder = { .pix_fmts = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}, .capabilities = CODEC_CAP_DELAY, }; - +#endif +#if CONFIG_A64MULTI5_ENCODER AVCodec ff_a64multi5_encoder = { .name = "a64multi5", .long_name = NULL_IF_CONFIG_SMALL("Multicolor charset for Commodore 64, extended with 5th color (colram)"), @@ -407,3 +421,4 @@ AVCodec ff_a64multi5_encoder = { .pix_fmts = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}, .capabilities = CODEC_CAP_DELAY, }; +#endif |