[FFmpeg-devel] A64 encoder
Michael Niedermayer
michaelni
Sat Jun 19 01:10:46 CEST 2010
On Tue, Jun 15, 2010 at 04:32:39PM +0200, Tobias Bindhammer wrote:
>>> + at item A64 multicolor @tab X @tab
>>> + @tab Creates video suitable to be played on a commodore 64
>>> (multicolor mode).
>>> @item 4X Movie @tab @tab X
>>> @tab Used in certain computer games.
>>> @item 8088flex TMV @tab @tab X
>> Didn't you add three different things?
>
> Yes, there are a few other formats available, but the consenus was, that
> we wanted to start with that one first to be added.
> Attached you'll find an updated diff with the suggested changes.
>
> regards,
>
> Toby
>
> --
> Dipl. Ing. Tobias Bindhammer
> Institut f?r Verteilte Systeme
> Oberer Eselsberg Phone: + 49 731/502-4235
> Universit?t Ulm Fax : + 49 731/502-4142
> D-89069 Ulm mailto:tobias.bindhammer at uni-ulm.de
> http://www-vs.informatik.uni-ulm.de/~bindhammer/
>
> doc/general.texi | 2
> libavcodec/Makefile | 2
> libavcodec/a64enc.h | 50 +++++++++
> libavcodec/a64multienc.c | 244 +++++++++++++++++++++++++++++++++++++++++++++++
> libavcodec/a64tables.h | 92 +++++++++++++++++
> libavcodec/allcodecs.c | 2
> libavcodec/avcodec.h | 2
> libavformat/Makefile | 1
> libavformat/a64.c | 73 ++++++++++++++
> libavformat/allformats.c | 1
please split muxer and codec into seperate patches so patches are smaller
[...]
> Index: libavcodec/avcodec.h
> ===================================================================
> --- libavcodec/avcodec.h (Revision 23561)
> +++ libavcodec/avcodec.h (Arbeitskopie)
> @@ -192,6 +192,8 @@
> CODEC_ID_MOTIONPIXELS,
> CODEC_ID_TGV,
> CODEC_ID_TGQ,
> + CODEC_ID_A64_MULTI,
> + CODEC_ID_A64_MULTI5,
> CODEC_ID_TQI,
> CODEC_ID_AURA,
> CODEC_ID_AURA2,
breaks ABI
[..]
> +#include "a64enc.h"
> +#include "a64tables.h"
> +#include "elbg.h"
> +
> +#define DITHERSTEPS 8
> +
> +/* own methods */
i think this is not the correct terminology for C
> +static void to_meta_with_crop(AVCodecContext *avctx, AVFrame *p, int *dest)
> +{
> + int blockx, blocky, x, y;
> + int luma = 0;
> + int height = FFMIN(avctx->height,C64YRES);
> + int width = FFMIN(avctx->width ,C64XRES);
> + uint8_t *src = p->data[0];
> +
> + for (blocky = 0; blocky<height; blocky += 8) {
> + for (blockx = 0; blockx<C64XRES; blockx += 8) {
> + for (y = blocky; y < blocky+8 && y<height; y++) {
> + for (x = blockx; x < blockx+8 && x<C64XRES; x += 2) {
> + if(x<width) {
> + /* build average over 2 pixels */
> + luma = (src[(x + 0 + y * p->linesize[0])] +
> + src[(x + 1 + y * p->linesize[0])]) / 2;
>>1
> + /* write blocks as linear data now so they are suitable for elbg */
> + dest[0] = luma;
> + }
> + dest++;
> + }
> + }
> + }
> + }
> +}
> +
> +static void render_charset(AVCodecContext *avctx, uint8_t *charset, uint8_t *colrammap)
> +{
> + A64Context *c = avctx->priv_data;
> + uint8_t row1;
> + int charpos, x, y;
> + int pix;
> + int dither;
> + int index1, index2;
> + int lowdiff, highdiff;
> + int maxindex = c->mc_use_5col + 3;
> + int maxsteps = DITHERSTEPS * maxindex + 1;
> + int *best_cb = c->mc_best_cb;
> +
> + /* now reduce colors first */
> + for (x = 0; x < 256 * 32; x++) best_cb[x] = best_cb[x] * maxsteps / 255;
> +
> + /* and render charset */
> + for (charpos = 0; charpos < 256; charpos++) {
> + lowdiff = 0;
> + highdiff = 0;
> + for (y = 0; y < 8; y++) {
> + row1 = 0;
> + for (x = 0; x < 4; x++) {
> + pix = best_cb[y * 4 + x];
> + dither = pix % DITHERSTEPS;
> + index1 = pix / DITHERSTEPS;
> + index2 = FFMIN(index1 + 1, maxindex);
> +
> + if (pix > 3 * DITHERSTEPS)
> + highdiff += pix - 3 * DITHERSTEPS;
> + if (pix < DITHERSTEPS)
> + lowdiff += DITHERSTEPS - pix;
> +
> + row1 <<= 2;
> + if (prep_dither_patterns[dither][y & 3][x & 3])
> + row1 |= 3-(index2 & 3);
> + else
> + row1 |= 3-(index1 & 3);
> + }
> + charset[y] = row1;
> + }
> +
> + /* are we in 5col mode and need to adjust pixels? */
> + if (c->mc_use_5col && highdiff > 0 && lowdiff > 0) {
> + if (lowdiff > highdiff) {
> + for (x = 0; x < 32; x++)
> + best_cb[x] = FFMIN(3 * DITHERSTEPS, best_cb[x]);
> + } else {
> + for (x = 0; x < 32; x++)
> + best_cb[x] = FFMAX(DITHERSTEPS, best_cb[x]);
> + }
> + charpos--; /* redo char */
> + } else {
> + /* advance pointers */
> + best_cb += 32;
> + charset += 8;
> +
> + if (highdiff > 0)
> + colrammap[charpos] = 0x9;
> + else
> + colrammap[charpos] = 0x8;
> + }
> + }
this heuristic is simply poor
if you had no success in implemening some error diffusion dither that considers
neighboring blocks and previous frames than i would suggest you at least try
some kind of a refinement pass after above
[...]
> +}
> +
> +/* encoder methods */
> +static av_cold int a64multi_close_encoder(AVCodecContext *avctx)
> +{
> + A64Context *c = avctx->priv_data;
> + av_free(c->mc_meta_charset);
> + av_free(c->mc_best_cb);
> + av_free(c->mc_charmap);
> + return 0;
> +}
> +
> +static av_cold int a64multi_init_encoder(AVCodecContext *avctx)
> +{
> + A64Context *c = avctx->priv_data;
> + av_lfg_init(&c->randctx, 1);
> +
> + if (avctx->global_quality < 1)
> + c->mc_lifetime = 4;
> + else
{} also try patcheck please
[...]
> +typedef struct A64Context {
> + /* general variables */
> + AVFrame picture;
> +
> + /* variables for multicolor modes */
> + AVLFG randctx;
> + int mc_lifetime;
> + int mc_use_5col;
> + int mc_frame_counter;
> + int *mc_meta_charset;
> + int *mc_charmap;
> + int *mc_best_cb;
> +} A64Context;
the encoders private struct belongs in the .c file unless the encoder is
split accross several files
[...]
> +
> +static int a64_write_header(struct AVFormatContext *s)
> +{
> + AVCodecContext *avctx=s->streams[0]->codec;
> + A64Context *c = avctx->priv_data;
the encoders private context is off limits for the muxer
it breaks stream copy but thats not the only reason
> + uint8_t header[5] = {
> + 0x00, //load
> + 0x40, //address
> + 0x00, //mode
> + 0x00, //charset_lifetime (multi only)
> + 0x00 //fps in 50/fps;
> + };
> + switch (avctx->codec->id) {
> + case CODEC_ID_A64_MULTI:
> + header[2]=0x00;
> + header[3]=c->mc_lifetime;
> + header[4]=2;
> + break;
> + case CODEC_ID_A64_MULTI5:
> + header[2]=0x01;
> + header[3]=c->mc_lifetime;
> + header[4]=3;
> + break;
> + default:
> + return -1;
> + break;
> + }
> + put_buffer(s->pb, header, 2);
a bunch of put_byte() seems simpler
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
The misfortune of the wise is better than the prosperity of the fool.
-- Epicurus
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20100619/b0796168/attachment.pgp>
More information about the ffmpeg-devel
mailing list