diff --git a/libavcodec/a64multienc.c b/libavcodec/a64multienc.c index e184ca9d29..d4659966aa 100644 --- a/libavcodec/a64multienc.c +++ b/libavcodec/a64multienc.c @@ -46,14 +46,14 @@ 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); + int height = FFMIN(avctx->height, C64YRES); + int width = FFMIN(avctx->width , C64XRES); uint8_t *src = p->data[0]; for (blocky = 0; blocky < C64YRES; blocky += 8) { for (blockx = 0; blockx < C64XRES; blockx += 8) { - for (y = blocky; y < blocky+8 && y < C64YRES; y++) { - for (x = blockx; x < blockx+8 && x < C64XRES; x += 2) { + 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])] + @@ -87,17 +87,18 @@ static void render_charset(AVCodecContext *avctx, uint8_t *charset, /* generate lookup-tables for dither and index before looping */ i = 0; for (a=0; a < 256; a++) { - if(i < c->mc_pal_size -1 && a == c->mc_luma_vals[i+1]) { - distance = c->mc_luma_vals[i+1] - c->mc_luma_vals[i]; + if(i < c->mc_pal_size -1 && a == c->mc_luma_vals[i + 1]) { + distance = c->mc_luma_vals[i + 1] - c->mc_luma_vals[i]; for(b = 0; b <= distance; b++) { - dither[c->mc_luma_vals[i]+b] = b * (DITHERSTEPS - 1) / distance; + dither[c->mc_luma_vals[i] + b] = b * (DITHERSTEPS - 1) / distance; } i++; } if(i >= c->mc_pal_size - 1) dither[a] = 0; index1[a] = i; - index2[a] = FFMIN(i+1, c->mc_pal_size - 1); + index2[a] = FFMIN(i + 1, c->mc_pal_size - 1); } + /* and render charset */ for (charpos = 0; charpos < CHARSET_CHARS; charpos++) { lowdiff = 0; @@ -115,7 +116,7 @@ static void render_charset(AVCodecContext *avctx, uint8_t *charset, row1 <<= 2; - if(INTERLACED) { + if (INTERLACED) { row2 <<= 2; if (interlaced_dither_patterns[dither[pix]][(y & 3) * 2 + 0][x & 3]) row1 |= 3-(index2[pix] & 3); @@ -135,7 +136,7 @@ static void render_charset(AVCodecContext *avctx, uint8_t *charset, } } charset[y+0x000] = row1; - if(INTERLACED) charset[y+0x800] = row2; + if (INTERLACED) charset[y+0x800] = row2; } /* do we need to adjust pixels? */ if (highdiff > 0 && lowdiff > 0 && c->mc_use_5col) { @@ -195,23 +196,23 @@ static av_cold int a64multi_init_encoder(AVCodecContext *avctx) a64_palette[mc_colors[a]][2] * 0.11; } - if(!(c->mc_meta_charset = av_malloc (32000 * c->mc_lifetime * 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_colram = av_mallocz(CHARSET_CHARS * sizeof(uint8_t))) || - !(c->mc_charset = av_malloc (0x800 * (INTERLACED+1) * sizeof(uint8_t)))) { + if (!(c->mc_meta_charset = av_malloc(32000 * c->mc_lifetime * 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_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"); return AVERROR(ENOMEM); } /* set up extradata */ - if(!(avctx->extradata = av_mallocz(8 * 4 + FF_INPUT_BUFFER_PADDING_SIZE))) { + if (!(avctx->extradata = av_mallocz(8 * 4 + FF_INPUT_BUFFER_PADDING_SIZE))) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate memory for extradata.\n"); return AVERROR(ENOMEM); } avctx->extradata_size = 8 * 4; AV_WB32(avctx->extradata, c->mc_lifetime); - AV_WB32(avctx->extradata+16, INTERLACED); + AV_WB32(avctx->extradata + 16, INTERLACED); avcodec_get_frame_defaults(&c->picture); avctx->coded_frame = &c->picture; @@ -233,7 +234,7 @@ static void a64_compress_colram(unsigned char *buf, int *charmap, uint8_t *colra temp = colram[charmap[a + 0x000]] << 0; temp |= colram[charmap[a + 0x100]] << 1; temp |= colram[charmap[a + 0x200]] << 2; - if(a < 0xe8) temp |= colram[charmap[a + 0x300]] << 3; + if (a < 0xe8) temp |= colram[charmap[a + 0x300]] << 3; buf[a] = temp << 2; } } @@ -251,17 +252,17 @@ static int a64multi_encode_frame(AVCodecContext *avctx, unsigned char *buf, int b_width; int req_size; - int num_frames = c->mc_lifetime; + int num_frames = c->mc_lifetime; - int *charmap = c->mc_charmap; - uint8_t *colram = c->mc_colram; - uint8_t *charset = c->mc_charset; - int *meta = c->mc_meta_charset; - int *best_cb = c->mc_best_cb; + int *charmap = c->mc_charmap; + uint8_t *colram = c->mc_colram; + uint8_t *charset = c->mc_charset; + int *meta = c->mc_meta_charset; + int *best_cb = c->mc_best_cb; int charset_size = 0x800 * (INTERLACED + 1); - int screen_size; int colram_size = 0x100 * c->mc_use_5col; + int screen_size; if(CROP_SCREENS) { b_height = FFMIN(avctx->height,C64YRES) >> 3; @@ -276,17 +277,16 @@ static int a64multi_encode_frame(AVCodecContext *avctx, unsigned char *buf, /* no data, means end encoding asap */ if (!data) { /* all done, end encoding */ - if(!c->mc_lifetime) return 0; + if (!c->mc_lifetime) return 0; /* no more frames in queue, prepare to flush remaining frames */ - if(!c->mc_frame_counter) { - num_frames=c->mc_lifetime; - c->mc_lifetime=0; + if (!c->mc_frame_counter) { + num_frames = c->mc_lifetime; + c->mc_lifetime = 0; } /* still frames in queue so limit lifetime to remaining frames */ - else c->mc_lifetime=c->mc_frame_counter; - } + else c->mc_lifetime = c->mc_frame_counter; /* still new data available */ - else { + } else { /* fill up mc_meta_charset with data until lifetime exceeds */ if (c->mc_frame_counter < c->mc_lifetime) { *p = *pict; @@ -303,7 +303,7 @@ static int a64multi_encode_frame(AVCodecContext *avctx, unsigned char *buf, if (c->mc_frame_counter == c->mc_lifetime) { req_size = 0; /* any frames to encode? */ - if(c->mc_lifetime) { + if (c->mc_lifetime) { /* calc optimal new charset + charmaps */ ff_init_elbg(meta, 32, 1000 * c->mc_lifetime, best_cb, CHARSET_CHARS, 50, charmap, &c->randctx); ff_do_elbg (meta, 32, 1000 * c->mc_lifetime, best_cb, CHARSET_CHARS, 50, charmap, &c->randctx); @@ -335,8 +335,8 @@ static int a64multi_encode_frame(AVCodecContext *avctx, unsigned char *buf, req_size += screen_size; /* compress and copy colram to buf */ - if(c->mc_use_5col) { - a64_compress_colram(buf,charmap,colram); + if (c->mc_use_5col) { + a64_compress_colram(buf, charmap, colram); /* advance pointers */ buf += colram_size; req_size += colram_size; @@ -346,9 +346,9 @@ static int a64multi_encode_frame(AVCodecContext *avctx, unsigned char *buf, charmap += 1000; } - AV_WB32(avctx->extradata+4, c->mc_frame_counter); - AV_WB32(avctx->extradata+8, charset_size); - AV_WB32(avctx->extradata+12, screen_size + colram_size); + AV_WB32(avctx->extradata + 4, c->mc_frame_counter); + AV_WB32(avctx->extradata + 8, charset_size); + AV_WB32(avctx->extradata + 12, screen_size + colram_size); /* reset counter */ c->mc_frame_counter = 0; diff --git a/libavformat/a64.c b/libavformat/a64.c index 66fbcaee40..2dc475cd5f 100644 --- a/libavformat/a64.c +++ b/libavformat/a64.c @@ -86,7 +86,7 @@ static int a64_write_packet(struct AVFormatContext *s, AVPacket *pkt) * the data for colram from/to ram first and waste too much time. If we interleave and send the * charset beforehand, we assemble a new charset chunk by chunk, write current screen data to * screen-ram to be displayed and decode the colram directly to colram-location $d800 during - * the overscan, while reading directly from source + * the overscan, while reading directly from source. * This is the only way so far, to achieve 25fps on c64 */ if(avctx->extradata) { /* fetch values from extradata */ @@ -96,33 +96,35 @@ static int a64_write_packet(struct AVFormatContext *s, AVPacket *pkt) frame_size = AV_RB32(avctx->extradata + 12); /* TODO: sanity checks? */ - } - else { + } else { av_log(avctx, AV_LOG_ERROR, "extradata not set\n"); return AVERROR(EINVAL); } + ch_chunksize=charset_size/lifetime; /* TODO: check if charset/size is % lifetime, but maybe check in codec */ + if(pkt->data) num_frames = lifetime; else num_frames = c->prev_frame_count; + for(i = 0; i < num_frames; i++) { if(pkt->data) { /* if available, put newest charset chunk into buffer */ put_buffer(s->pb, pkt->data + ch_chunksize * i, ch_chunksize); - } - else { + } else { /* a bit ugly, but is there an alternative to put many zeros? */ for(j = 0; j < ch_chunksize; j++) put_byte(s->pb, 0); } + if(c->prev_pkt.data) { /* put frame (screen + colram) from last packet into buffer */ put_buffer(s->pb, c->prev_pkt.data + charset_size + frame_size * i, frame_size); - } - else { + } else { /* a bit ugly, but is there an alternative to put many zeros? */ for(j = 0; j < frame_size; j++) put_byte(s->pb, 0); } } + /* backup current packet for next turn */ if(pkt->data) { /* no backup packet yet? create one! */ @@ -136,6 +138,7 @@ static int a64_write_packet(struct AVFormatContext *s, AVPacket *pkt) return AVERROR(ENOMEM); } } + c->prev_frame_count = frame_count; break; }