00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00029 #include <string.h>
00030
00031 #include "avcodec.h"
00032 #include "internal.h"
00033 #include "libavutil/internal.h"
00034 #include "libavutil/xga_font_data.h"
00035
00036 #include "cga_data.h"
00037
00038 typedef struct TMVContext {
00039 AVFrame pic;
00040 } TMVContext;
00041
00042 static int tmv_decode_frame(AVCodecContext *avctx, void *data,
00043 int *got_frame, AVPacket *avpkt)
00044 {
00045 TMVContext *tmv = avctx->priv_data;
00046 const uint8_t *src = avpkt->data;
00047 uint8_t *dst;
00048 unsigned char_cols = avctx->width >> 3;
00049 unsigned char_rows = avctx->height >> 3;
00050 unsigned x, y, fg, bg, c;
00051
00052 if (tmv->pic.data[0])
00053 avctx->release_buffer(avctx, &tmv->pic);
00054
00055 if (ff_get_buffer(avctx, &tmv->pic) < 0) {
00056 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00057 return -1;
00058 }
00059
00060 if (avpkt->size < 2*char_rows*char_cols) {
00061 av_log(avctx, AV_LOG_ERROR,
00062 "Input buffer too small, truncated sample?\n");
00063 *got_frame = 0;
00064 return -1;
00065 }
00066
00067 tmv->pic.pict_type = AV_PICTURE_TYPE_I;
00068 tmv->pic.key_frame = 1;
00069 dst = tmv->pic.data[0];
00070
00071 tmv->pic.palette_has_changed = 1;
00072 memcpy(tmv->pic.data[1], ff_cga_palette, 16 * 4);
00073
00074 for (y = 0; y < char_rows; y++) {
00075 for (x = 0; x < char_cols; x++) {
00076 c = *src++;
00077 bg = *src >> 4;
00078 fg = *src++ & 0xF;
00079 ff_draw_pc_font(dst + x * 8, tmv->pic.linesize[0],
00080 avpriv_cga_font, 8, c, fg, bg);
00081 }
00082 dst += tmv->pic.linesize[0] * 8;
00083 }
00084
00085 *got_frame = 1;
00086 *(AVFrame *)data = tmv->pic;
00087 return avpkt->size;
00088 }
00089
00090 static av_cold int tmv_decode_init(AVCodecContext *avctx)
00091 {
00092 TMVContext *tmv = avctx->priv_data;
00093 avctx->pix_fmt = AV_PIX_FMT_PAL8;
00094 avcodec_get_frame_defaults(&tmv->pic);
00095 return 0;
00096 }
00097
00098 static av_cold int tmv_decode_close(AVCodecContext *avctx)
00099 {
00100 TMVContext *tmv = avctx->priv_data;
00101
00102 if (tmv->pic.data[0])
00103 avctx->release_buffer(avctx, &tmv->pic);
00104
00105 return 0;
00106 }
00107
00108 AVCodec ff_tmv_decoder = {
00109 .name = "tmv",
00110 .type = AVMEDIA_TYPE_VIDEO,
00111 .id = AV_CODEC_ID_TMV,
00112 .priv_data_size = sizeof(TMVContext),
00113 .init = tmv_decode_init,
00114 .close = tmv_decode_close,
00115 .decode = tmv_decode_frame,
00116 .capabilities = CODEC_CAP_DR1,
00117 .long_name = NULL_IF_CONFIG_SMALL("8088flex TMV"),
00118 };