static int h261_decode_frame(AVCodecContext *avctx, void *data, int *data_size, const uint8_t *buf, int buf_size) { H261Context *h= avctx->priv_data; MpegEncContext *s = &h->s; int ret; AVFrame *pict = data; #ifdef DEBUG av_log(avctx, AV_LOG_DEBUG, "*****frame %d size=%d\n", avctx->frame_number, buf_size); av_log(avctx, AV_LOG_DEBUG, "bytes=%x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]); #endif s->flags= avctx->flags; s->flags2= avctx->flags2; h->gob_start_code_skipped=0; retry: init_get_bits(&s->gb, buf, buf_size*8); if(!s->context_initialized){ if (MPV_common_init(s) < 0) //we need the idct permutaton for reading a custom matrix return -1; } //we need to set current_picture_ptr before reading the header, otherwise we cannot store anyting im there if(s->current_picture_ptr==NULL || s->current_picture_ptr->data[0]){ int i= ff_find_unused_picture(s, 0); s->current_picture_ptr= &s->picture[i]; } ret = h261_decode_picture_header(h); /* skip if the header was thrashed */ if (ret < 0){ av_log(s->avctx, AV_LOG_ERROR, "header damaged\n"); return -1; } if (s->width != avctx->coded_width || s->height != avctx->coded_height){ ParseContext pc= s->parse_context; //FIXME move this demuxing hack to libavformat s->parse_context.buffer=0; MPV_common_end(s); s->parse_context= pc; } if (!s->context_initialized) { avcodec_set_dimensions(avctx, s->width, s->height); goto retry; } // for hurry_up==5 s->current_picture.pict_type= s->pict_type; s->current_picture.key_frame= s->pict_type == FF_I_TYPE; /* skip everything if we are in a hurry>=5 */ if(avctx->hurry_up>=5) return get_consumed_bytes(s, buf_size); if( (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type==FF_B_TYPE) ||(avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type!=FF_I_TYPE) || avctx->skip_frame >= AVDISCARD_ALL) return get_consumed_bytes(s, buf_size); if(MPV_frame_start(s, avctx) < 0) return -1; ff_er_frame_start(s); /* decode each macroblock */ s->mb_x=0; s->mb_y=0; while(h->gob_number < (s->mb_height==18 ? 12 : 5)){ if(ff_h261_resync(h)<0) break; h261_decode_gob(h); } MPV_frame_end(s); assert(s->current_picture.pict_type == s->current_picture_ptr->pict_type); assert(s->current_picture.pict_type == s->pict_type); *pict= *(AVFrame*)s->current_picture_ptr; ff_print_debug_info(s, pict); *data_size = sizeof(AVFrame); return get_consumed_bytes(s, buf_size); }
static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) { SgiState *s = avctx->priv_data; AVFrame *picture = data; AVFrame *p = &s->picture; unsigned int dimension, rle; int ret = 0; uint8_t *out_buf, *out_end; bytestream2_init(&s->g, avpkt->data, avpkt->size); if (bytestream2_get_bytes_left(&s->g) < SGI_HEADER_SIZE) { av_log(avctx, AV_LOG_ERROR, "buf_size too small (%d)\n", avpkt->size); return AVERROR_INVALIDDATA; } /* Test for SGI magic. */ if (bytestream2_get_be16(&s->g) != SGI_MAGIC) { av_log(avctx, AV_LOG_ERROR, "bad magic number\n"); return AVERROR_INVALIDDATA; } rle = bytestream2_get_byte(&s->g); s->bytes_per_channel = bytestream2_get_byte(&s->g); dimension = bytestream2_get_be16(&s->g); s->width = bytestream2_get_be16(&s->g); s->height = bytestream2_get_be16(&s->g); s->depth = bytestream2_get_be16(&s->g); if (s->bytes_per_channel != 1 && (s->bytes_per_channel != 2 || rle)) { av_log(avctx, AV_LOG_ERROR, "wrong channel number\n"); return -1; } /* Check for supported image dimensions. */ if (dimension != 2 && dimension != 3) { av_log(avctx, AV_LOG_ERROR, "wrong dimension number\n"); return -1; } if (s->depth == SGI_GRAYSCALE) { avctx->pix_fmt = s->bytes_per_channel == 2 ? PIX_FMT_GRAY16BE : PIX_FMT_GRAY8; } else if (s->depth == SGI_RGB) { avctx->pix_fmt = s->bytes_per_channel == 2 ? PIX_FMT_RGB48BE : PIX_FMT_RGB24; } else if (s->depth == SGI_RGBA) { avctx->pix_fmt = s->bytes_per_channel == 2 ? PIX_FMT_RGBA64BE : PIX_FMT_RGBA; } else { av_log(avctx, AV_LOG_ERROR, "wrong picture format\n"); return -1; } if (av_image_check_size(s->width, s->height, 0, avctx)) return -1; avcodec_set_dimensions(avctx, s->width, s->height); if (p->data[0]) avctx->release_buffer(avctx, p); p->reference = 0; if (avctx->get_buffer(avctx, p) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed.\n"); return -1; } p->pict_type = AV_PICTURE_TYPE_I; p->key_frame = 1; out_buf = p->data[0]; out_end = out_buf + p->linesize[0] * s->height; s->linesize = p->linesize[0]; /* Skip header. */ bytestream2_seek(&s->g, SGI_HEADER_SIZE, SEEK_SET); if (rle) { ret = read_rle_sgi(out_end, s); } else { ret = read_uncompressed_sgi(out_buf, out_end, s); } if (ret == 0) { *picture = s->picture; *data_size = sizeof(AVPicture); return avpkt->size; } else { return ret; } }
/** * Execute ANSI escape code * @return 0 on success, negative on error */ static int execute_code(AVCodecContext * avctx, int c) { AnsiContext *s = avctx->priv_data; int ret, i, width, height; switch(c) { case 'A': //Cursor Up s->y = FFMAX(s->y - (s->nb_args > 0 ? s->args[0]*s->font_height : s->font_height), 0); break; case 'B': //Cursor Down s->y = FFMIN(s->y + (s->nb_args > 0 ? s->args[0]*s->font_height : s->font_height), avctx->height - s->font_height); break; case 'C': //Cursor Right s->x = FFMIN(s->x + (s->nb_args > 0 ? s->args[0]*FONT_WIDTH : FONT_WIDTH), avctx->width - FONT_WIDTH); break; case 'D': //Cursor Left s->x = FFMAX(s->x - (s->nb_args > 0 ? s->args[0]*FONT_WIDTH : FONT_WIDTH), 0); break; case 'H': //Cursor Position case 'f': //Horizontal and Vertical Position s->y = s->nb_args > 0 ? av_clip((s->args[0] - 1)*s->font_height, 0, avctx->height - s->font_height) : 0; s->x = s->nb_args > 1 ? av_clip((s->args[1] - 1)*FONT_WIDTH, 0, avctx->width - FONT_WIDTH) : 0; break; case 'h': //set creen mode case 'l': //reset screen mode if (s->nb_args < 2) s->args[0] = DEFAULT_SCREEN_MODE; width = avctx->width; height = avctx->height; switch(s->args[0]) { case 0: case 1: case 4: case 5: case 13: case 19: //320x200 (25 rows) s->font = avpriv_cga_font; s->font_height = 8; width = 40<<3; height = 25<<3; break; case 2: case 3: //640x400 (25 rows) s->font = avpriv_vga16_font; s->font_height = 16; width = 80<<3; height = 25<<4; break; case 6: case 14: //640x200 (25 rows) s->font = avpriv_cga_font; s->font_height = 8; width = 80<<3; height = 25<<3; break; case 7: //set line wrapping break; case 15: case 16: //640x350 (43 rows) s->font = avpriv_cga_font; s->font_height = 8; width = 80<<3; height = 43<<3; break; case 17: case 18: //640x480 (60 rows) s->font = avpriv_cga_font; s->font_height = 8; width = 80<<3; height = 60<<4; break; default: avpriv_request_sample(avctx, "Unsupported screen mode"); } s->x = av_clip(s->x, 0, width - FONT_WIDTH); s->y = av_clip(s->y, 0, height - s->font_height); if (width != avctx->width || height != avctx->height) { av_frame_unref(s->frame); avcodec_set_dimensions(avctx, width, height); if ((ret = ff_get_buffer(avctx, s->frame, AV_GET_BUFFER_FLAG_REF)) < 0) return ret; s->frame->pict_type = AV_PICTURE_TYPE_I; s->frame->palette_has_changed = 1; set_palette((uint32_t *)s->frame->data[1]); erase_screen(avctx); } else if (c == 'l') { erase_screen(avctx); } break; case 'J': //Erase in Page switch (s->args[0]) { case 0: erase_line(avctx, s->x, avctx->width - s->x); if (s->y < avctx->height - s->font_height) memset(s->frame->data[0] + (s->y + s->font_height)*s->frame->linesize[0], DEFAULT_BG_COLOR, (avctx->height - s->y - s->font_height)*s->frame->linesize[0]); break; case 1: erase_line(avctx, 0, s->x); if (s->y > 0) memset(s->frame->data[0], DEFAULT_BG_COLOR, s->y * s->frame->linesize[0]); break; case 2: erase_screen(avctx); } break; case 'K': //Erase in Line switch(s->args[0]) { case 0: erase_line(avctx, s->x, avctx->width - s->x); break; case 1: erase_line(avctx, 0, s->x); break; case 2: erase_line(avctx, 0, avctx->width); } break; case 'm': //Select Graphics Rendition if (s->nb_args == 0) { s->nb_args = 1; s->args[0] = 0; } for (i = 0; i < FFMIN(s->nb_args, MAX_NB_ARGS); i++) { int m = s->args[i]; if (m == 0) { s->attributes = 0; s->fg = DEFAULT_FG_COLOR; s->bg = DEFAULT_BG_COLOR; } else if (m == 1 || m == 2 || m == 4 || m == 5 || m == 7 || m == 8) { s->attributes |= 1 << (m - 1); } else if (m >= 30 && m <= 37) { s->fg = ansi_to_cga[m - 30]; } else if (m == 38 && i + 2 < FFMIN(s->nb_args, MAX_NB_ARGS) && s->args[i + 1] == 5 && s->args[i + 2] < 256) { int index = s->args[i + 2]; s->fg = index < 16 ? ansi_to_cga[index] : index; i += 2; } else if (m == 39) { s->fg = ansi_to_cga[DEFAULT_FG_COLOR]; } else if (m >= 40 && m <= 47) { s->bg = ansi_to_cga[m - 40]; } else if (m == 48 && i + 2 < FFMIN(s->nb_args, MAX_NB_ARGS) && s->args[i + 1] == 5 && s->args[i + 2] < 256) { int index = s->args[i + 2]; s->bg = index < 16 ? ansi_to_cga[index] : index; i += 2; } else if (m == 49) { s->fg = ansi_to_cga[DEFAULT_BG_COLOR]; } else { avpriv_request_sample(avctx, "Unsupported rendition parameter"); } } break; case 'n': //Device Status Report case 'R': //report current line and column /* ignore */ break; case 's': //Save Cursor Position s->sx = s->x; s->sy = s->y; break; case 'u': //Restore Cursor Position s->x = av_clip(s->sx, 0, avctx->width - FONT_WIDTH); s->y = av_clip(s->sy, 0, avctx->height - s->font_height); break; default: avpriv_request_sample(avctx, "Unknown escape code"); break; } s->x = av_clip(s->x, 0, avctx->width - FONT_WIDTH); s->y = av_clip(s->y, 0, avctx->height - s->font_height); return 0; }
static int rv20_decode_picture_header(MpegEncContext *s) { int seq, mb_pos, i; #if 0 GetBitContext gb= s->gb; for(i=0; i<64; i++){ av_log(s->avctx, AV_LOG_DEBUG, "%d", get_bits1(&gb)); if(i%4==3) av_log(s->avctx, AV_LOG_DEBUG, " "); } av_log(s->avctx, AV_LOG_DEBUG, "\n"); #endif #if 0 av_log(s->avctx, AV_LOG_DEBUG, "%3dx%03d/%02Xx%02X ", s->width, s->height, s->width/4, s->height/4); for(i=0; i<s->avctx->extradata_size; i++){ av_log(s->avctx, AV_LOG_DEBUG, "%02X ", ((uint8_t*)s->avctx->extradata)[i]); if(i%4==3) av_log(s->avctx, AV_LOG_DEBUG, " "); } av_log(s->avctx, AV_LOG_DEBUG, "\n"); #endif if(s->avctx->sub_id == 0x30202002 || s->avctx->sub_id == 0x30203002){ if (get_bits(&s->gb, 3)){ av_log(s->avctx, AV_LOG_ERROR, "unknown triplet set\n"); return -1; } } i= get_bits(&s->gb, 2); switch(i){ case 0: s->pict_type= FF_I_TYPE; break; case 1: s->pict_type= FF_I_TYPE; break; //hmm ... case 2: s->pict_type= FF_P_TYPE; break; case 3: s->pict_type= FF_B_TYPE; break; default: av_log(s->avctx, AV_LOG_ERROR, "unknown frame type\n"); return -1; } if(s->last_picture_ptr==NULL && s->pict_type==FF_B_TYPE){ av_log(s->avctx, AV_LOG_ERROR, "early B pix\n"); return -1; } if (get_bits1(&s->gb)){ av_log(s->avctx, AV_LOG_ERROR, "unknown bit set\n"); return -1; } s->qscale = get_bits(&s->gb, 5); if(s->qscale==0){ av_log(s->avctx, AV_LOG_ERROR, "error, qscale:0\n"); return -1; } if(s->avctx->sub_id == 0x30203002){ if (get_bits1(&s->gb)){ av_log(s->avctx, AV_LOG_ERROR, "unknown bit2 set\n"); return -1; } } if(s->avctx->has_b_frames){ int f, new_w, new_h; int v= s->avctx->extradata_size >= 4 ? 7&((uint8_t*)s->avctx->extradata)[1] : 0; if (get_bits1(&s->gb)){ av_log(s->avctx, AV_LOG_ERROR, "unknown bit3 set\n"); } seq= get_bits(&s->gb, 13)<<2; f= get_bits(&s->gb, av_log2(v)+1); if(f){ new_w= 4*((uint8_t*)s->avctx->extradata)[6+2*f]; new_h= 4*((uint8_t*)s->avctx->extradata)[7+2*f]; }else{ new_w= s->orig_width ; new_h= s->orig_height; } if(new_w != s->width || new_h != s->height){ av_log(s->avctx, AV_LOG_DEBUG, "attempting to change resolution to %dx%d\n", new_w, new_h); if (avcodec_check_dimensions(s->avctx, new_w, new_h) < 0) return -1; MPV_common_end(s); avcodec_set_dimensions(s->avctx, new_w, new_h); s->width = new_w; s->height = new_h; if (MPV_common_init(s) < 0) return -1; } if(s->avctx->debug & FF_DEBUG_PICT_INFO){ av_log(s->avctx, AV_LOG_DEBUG, "F %d/%d\n", f, v); } }else{ seq= get_bits(&s->gb, 8)*128; } // if(s->avctx->sub_id <= 0x20201002){ //0x20201002 definitely needs this mb_pos= ff_h263_decode_mba(s); /* }else{ mb_pos= get_bits(&s->gb, av_log2(s->mb_num-1)+1); s->mb_x= mb_pos % s->mb_width; s->mb_y= mb_pos / s->mb_width; }*/ //av_log(s->avctx, AV_LOG_DEBUG, "%d\n", seq); seq |= s->time &~0x7FFF; if(seq - s->time > 0x4000) seq -= 0x8000; if(seq - s->time < -0x4000) seq += 0x8000; if(seq != s->time){ if(s->pict_type!=FF_B_TYPE){ s->time= seq; s->pp_time= s->time - s->last_non_b_time; s->last_non_b_time= s->time; }else{ s->time= seq; s->pb_time= s->pp_time - (s->last_non_b_time - s->time); if(s->pp_time <=s->pb_time || s->pp_time <= s->pp_time - s->pb_time || s->pp_time<=0){ av_log(s->avctx, AV_LOG_DEBUG, "messed up order, possible from seeking? skipping current b frame\n"); return FRAME_SKIPPED; } ff_mpeg4_init_direct_mv(s); } } // printf("%d %d %d %d %d\n", seq, (int)s->time, (int)s->last_non_b_time, s->pp_time, s->pb_time); /*for(i=0; i<32; i++){ av_log(s->avctx, AV_LOG_DEBUG, "%d", get_bits1(&s->gb)); } av_log(s->avctx, AV_LOG_DEBUG, "\n");*/ s->no_rounding= get_bits1(&s->gb); s->f_code = 1; s->unrestricted_mv = 1; s->h263_aic= s->pict_type == FF_I_TYPE; // s->alt_inter_vlc=1; // s->obmc=1; // s->umvplus=1; s->modified_quant=1; if(!s->avctx->lowres) s->loop_filter=1; if(s->avctx->debug & FF_DEBUG_PICT_INFO){ av_log(s->avctx, AV_LOG_INFO, "num:%5d x:%2d y:%2d type:%d qscale:%2d rnd:%d\n", seq, s->mb_x, s->mb_y, s->pict_type, s->qscale, s->no_rounding); } assert(s->pict_type != FF_B_TYPE || !s->low_delay); return s->mb_width*s->mb_height - mb_pos; }
/* Returns the number of bytes consumed from the bytestream. Returns -1 if * there was an error while decoding the header */ static int truemotion1_decode_header(TrueMotion1Context *s) { int i; int width_shift = 0; int new_pix_fmt; struct frame_header header; uint8_t header_buffer[128] = { 0 }; /* logical maximum size of the header */ const uint8_t *sel_vector_table; header.header_size = ((s->buf[0] >> 5) | (s->buf[0] << 3)) & 0x7f; if (s->buf[0] < 0x10 || header.header_size >= s->size) { av_log(s->avctx, AV_LOG_ERROR, "invalid header size (%d)\n", s->buf[0]); return -1; } /* unscramble the header bytes with a XOR operation */ for (i = 1; i < header.header_size; i++) header_buffer[i - 1] = s->buf[i] ^ s->buf[i + 1]; header.compression = header_buffer[0]; header.deltaset = header_buffer[1]; header.vectable = header_buffer[2]; header.ysize = AV_RL16(&header_buffer[3]); header.xsize = AV_RL16(&header_buffer[5]); header.checksum = AV_RL16(&header_buffer[7]); header.version = header_buffer[9]; header.header_type = header_buffer[10]; header.flags = header_buffer[11]; header.control = header_buffer[12]; /* Version 2 */ if (header.version >= 2) { if (header.header_type > 3) { av_log(s->avctx, AV_LOG_ERROR, "invalid header type (%d)\n", header.header_type); return -1; } else if ((header.header_type == 2) || (header.header_type == 3)) { s->flags = header.flags; if (!(s->flags & FLAG_INTERFRAME)) s->flags |= FLAG_KEYFRAME; } else s->flags = FLAG_KEYFRAME; } else /* Version 1 */ s->flags = FLAG_KEYFRAME; if (s->flags & FLAG_SPRITE) { av_log_ask_for_sample(s->avctx, "SPRITE frame found.\n"); /* FIXME header.width, height, xoffset and yoffset aren't initialized */ return AVERROR_PATCHWELCOME; } else { s->w = header.xsize; s->h = header.ysize; if (header.header_type < 2) { if ((s->w < 213) && (s->h >= 176)) { s->flags |= FLAG_INTERPOLATED; av_log_ask_for_sample(s->avctx, "INTERPOLATION selected.\n"); } } } if (header.compression >= 17) { av_log(s->avctx, AV_LOG_ERROR, "invalid compression type (%d)\n", header.compression); return -1; } if ((header.deltaset != s->last_deltaset) || (header.vectable != s->last_vectable)) select_delta_tables(s, header.deltaset); if ((header.compression & 1) && header.header_type) sel_vector_table = pc_tbl2; else { if (header.vectable > 0 && header.vectable < 4) sel_vector_table = tables[header.vectable - 1]; else { av_log(s->avctx, AV_LOG_ERROR, "invalid vector table id (%d)\n", header.vectable); return -1; } } if (compression_types[header.compression].algorithm == ALGO_RGB24H) { new_pix_fmt = AV_PIX_FMT_RGB32; width_shift = 1; } else new_pix_fmt = AV_PIX_FMT_RGB555; // RGB565 is supported as well s->w >>= width_shift; if (av_image_check_size(s->w, s->h, 0, s->avctx) < 0) return -1; if (s->w != s->avctx->width || s->h != s->avctx->height || new_pix_fmt != s->avctx->pix_fmt) { if (s->frame.data[0]) s->avctx->release_buffer(s->avctx, &s->frame); s->avctx->sample_aspect_ratio = (AVRational){ 1 << width_shift, 1 }; s->avctx->pix_fmt = new_pix_fmt; avcodec_set_dimensions(s->avctx, s->w, s->h); av_fast_malloc(&s->vert_pred, &s->vert_pred_size, s->avctx->width * sizeof(unsigned int)); } /* There is 1 change bit per 4 pixels, so each change byte represents * 32 pixels; divide width by 4 to obtain the number of change bits and * then round up to the nearest byte. */ s->mb_change_bits_row_size = ((s->avctx->width >> (2 - width_shift)) + 7) >> 3; if ((header.deltaset != s->last_deltaset) || (header.vectable != s->last_vectable)) { if (compression_types[header.compression].algorithm == ALGO_RGB24H) gen_vector_table24(s, sel_vector_table); else if (s->avctx->pix_fmt == AV_PIX_FMT_RGB555) gen_vector_table15(s, sel_vector_table); else gen_vector_table16(s, sel_vector_table); } /* set up pointers to the other key data chunks */ s->mb_change_bits = s->buf + header.header_size; if (s->flags & FLAG_KEYFRAME) { /* no change bits specified for a keyframe; only index bytes */ s->index_stream = s->mb_change_bits; } else { /* one change bit per 4x4 block */ s->index_stream = s->mb_change_bits + (s->mb_change_bits_row_size * (s->avctx->height >> 2)); } s->index_stream_size = s->size - (s->index_stream - s->buf); s->last_deltaset = header.deltaset; s->last_vectable = header.vectable; s->compression = header.compression; s->block_width = compression_types[header.compression].block_width; s->block_height = compression_types[header.compression].block_height; s->block_type = compression_types[header.compression].block_type; if (s->avctx->debug & FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_INFO, "tables: %d / %d c:%d %dx%d t:%d %s%s%s%s\n", s->last_deltaset, s->last_vectable, s->compression, s->block_width, s->block_height, s->block_type, s->flags & FLAG_KEYFRAME ? " KEY" : "", s->flags & FLAG_INTERFRAME ? " INTER" : "", s->flags & FLAG_SPRITE ? " SPRITE" : "", s->flags & FLAG_INTERPOLATED ? " INTERPOL" : ""); return header.header_size; }
static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) { PicContext *s = avctx->priv_data; int buf_size = avpkt->size; const uint8_t *buf = avpkt->data; const uint8_t *buf_end = avpkt->data + buf_size; uint32_t *palette; int bits_per_plane, bpp, etype, esize, npal; int i, x, y, plane; if (buf_size < 11) return AVERROR_INVALIDDATA; if (bytestream_get_le16(&buf) != 0x1234) return AVERROR_INVALIDDATA; s->width = bytestream_get_le16(&buf); s->height = bytestream_get_le16(&buf); buf += 4; bits_per_plane = *buf & 0xF; s->nb_planes = (*buf++ >> 4) + 1; bpp = s->nb_planes ? bits_per_plane*s->nb_planes : bits_per_plane; if (bits_per_plane > 8 || bpp < 1 || bpp > 32) { av_log_ask_for_sample(s, "unsupported bit depth\n"); return AVERROR_INVALIDDATA; } if (*buf == 0xFF) { buf += 2; etype = bytestream_get_le16(&buf); esize = bytestream_get_le16(&buf); if (buf_end - buf < esize) return AVERROR_INVALIDDATA; } else { etype = -1; esize = 0; } avctx->pix_fmt = PIX_FMT_PAL8; if (s->width != avctx->width && s->height != avctx->height) { if (av_image_check_size(s->width, s->height, 0, avctx) < 0) return -1; avcodec_set_dimensions(avctx, s->width, s->height); if (s->frame.data[0]) avctx->release_buffer(avctx, &s->frame); } if (avctx->get_buffer(avctx, &s->frame) < 0){ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return -1; } memset(s->frame.data[0], 0, s->height * s->frame.linesize[0]); s->frame.pict_type = AV_PICTURE_TYPE_I; s->frame.palette_has_changed = 1; palette = (uint32_t*)s->frame.data[1]; if (etype == 1 && esize > 1 && *buf < 6) { int idx = *buf; npal = 4; for (i = 0; i < npal; i++) palette[i] = ff_cga_palette[ cga_mode45_index[idx][i] ]; } else if (etype == 2) { npal = FFMIN(esize, 16); for (i = 0; i < npal; i++) palette[i] = ff_cga_palette[ FFMIN(buf[i], 16)]; } else if (etype == 3) { npal = FFMIN(esize, 16); for (i = 0; i < npal; i++) palette[i] = ff_ega_palette[ FFMIN(buf[i], 63)]; } else if (etype == 4 || etype == 5) { npal = FFMIN(esize / 3, 256); for (i = 0; i < npal; i++) palette[i] = AV_RB24(buf + i*3) << 2; } else { if (bpp == 1) { npal = 2; palette[0] = 0x000000; palette[1] = 0xFFFFFF; } else if (bpp == 2) { npal = 4; for (i = 0; i < npal; i++) palette[i] = ff_cga_palette[ cga_mode45_index[0][i] ]; } else { npal = 16; memcpy(palette, ff_cga_palette, npal * 4); } } // fill remaining palette entries memset(palette + npal, 0, AVPALETTE_SIZE - npal * 4); buf += esize; x = 0; y = s->height - 1; plane = 0; if (bytestream_get_le16(&buf)) { while (buf_end - buf >= 6) { const uint8_t *buf_pend = buf + FFMIN(AV_RL16(buf), buf_end - buf); //ignore uncompressed block size reported at buf[2] int marker = buf[4]; buf += 5; while (plane < s->nb_planes && buf_pend - buf >= 1) { int run = 1; int val = *buf++; if (val == marker) { run = *buf++; if (run == 0) run = bytestream_get_le16(&buf); val = *buf++; } if (buf > buf_end) break; if (bits_per_plane == 8) { picmemset_8bpp(s, val, run, &x, &y); if (y < 0) break; } else { picmemset(s, val, run, &x, &y, &plane, bits_per_plane); } } } } else { av_log_ask_for_sample(s, "uncompressed image\n"); return buf_size; } *data_size = sizeof(AVFrame); *(AVFrame*)data = s->frame; return buf_size; }