m_config.c: cosmetics: Move functions to avoid forward declarations
[mplayer.git] / libmpcodecs / vd_mtga.c
blob390166a3e6eaae70095c4615baa0528c0fdc457a
1 /*
2 * based on: XreaL's x_r_img_tga.* (http://www.sourceforge.net/projects/xreal/)
3 * libtarga.*
4 * xli's tga.*
6 * Copyright (c) 2002 Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
8 * This file is part of MPlayer.
10 * MPlayer is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * MPlayer is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
29 #include "config.h"
30 #include "mp_msg.h"
32 #include "ffmpeg_files/intreadwrite.h"
33 #include "libvo/fastmemcpy.h"
35 #include "vd_internal.h"
37 static const vd_info_t info =
39 "TGA Images decoder",
40 "mtga",
41 "Tilman Sauerbeck, A'rpi",
42 "Tilman Sauerbeck",
43 "only 24bpp and 32bpp RGB targa files support so far"
46 LIBVD_EXTERN(mtga)
48 typedef enum
50 TGA_NO_DATA,
51 TGA_UNCOMP_PALETTED,
52 TGA_UNCOMP_TRUECOLOR,
53 TGA_UNCOMP_GRAYSCALE,
54 TGA_RLE_PALETTED = 9,
55 TGA_RLE_TRUECOLOR,
56 TGA_RLE_GRAYSCALE
57 } TGAImageType;
59 typedef struct
61 unsigned char id_len;
62 unsigned short img_type;
64 unsigned short width;
65 unsigned short height;
67 unsigned char bpp;
68 unsigned char origin; /* 0 = lower left, 1 = upper left */
69 unsigned short start_row;
70 short increment;
71 } TGAInfo;
73 static unsigned int out_fmt = 0;
75 static int last_w = -1;
76 static int last_h = -1;
77 static int last_c = -1;
80 /* to set/get/query special features/parameters */
81 static int control(sh_video_t *sh, int cmd, void *arg, ...)
83 switch (cmd)
85 case VDCTRL_QUERY_FORMAT:
86 if (*((int *) arg) == out_fmt) return CONTROL_TRUE;
87 return CONTROL_FALSE;
89 return CONTROL_UNKNOWN;
92 /* init driver */
93 static int init(sh_video_t *sh)
95 sh->context = calloc(1, sizeof(TGAInfo));
96 last_w = -1;
98 return 1;
102 /* uninit driver */
103 static void uninit(sh_video_t *sh)
105 TGAInfo *info = sh->context;
106 free(info);
107 return;
111 /* decode a runlength-encoded tga */
112 static void decode_rle_tga(TGAInfo *info, unsigned char *data, mp_image_t *mpi)
114 int row, col, replen, i, num_bytes = info->bpp / 8;
115 unsigned char repetitions, packet_header, *final;
117 /* see line 207 to see why this loop is set up like this */
118 for (row = info->start_row; (!info->origin && row) || (info->origin && row < info->height); row += info->increment)
120 final = mpi->planes[0] + mpi->stride[0] * row;
122 for (col = 0; col < info->width; col += repetitions)
124 packet_header = *data++;
125 repetitions = (1 + (packet_header & 0x7f));
126 replen = repetitions * num_bytes;
128 if (packet_header & 0x80) /* runlength encoded packet */
130 memcpy(final, data, num_bytes);
132 // Note: this will be slow when DR to vram!
133 i=num_bytes;
134 while(2*i<=replen){
135 memcpy(final+i,final,i);
136 i*=2;
138 memcpy(final+i,final,replen-i);
139 data += num_bytes;
141 else /* raw packet */
143 fast_memcpy(final, data, replen);
144 data += replen;
147 final += replen;
151 return;
155 static void decode_uncompressed_tga(TGAInfo *info, unsigned char *data, mp_image_t *mpi)
157 unsigned char *final;
158 int row, num_bytes = info->bpp / 8;
160 /* see line 207 to see why this loop is set up like this */
161 for (row = info->start_row; (!info->origin && row) || (info->origin && row < info->height); row += info->increment)
163 final = mpi->planes[0] + mpi->stride[0] * row;
164 fast_memcpy(final, data, info->width * num_bytes);
165 data += info->width * num_bytes;
168 return;
172 static short read_tga_header(unsigned char *buf, TGAInfo *info)
174 info->id_len = buf[0];
176 info->img_type = buf[2];
178 /* targa data is always stored in little endian byte order */
179 info->width = AV_RL16(&buf[12]);
180 info->height = AV_RL16(&buf[14]);
182 info->bpp = buf[16];
184 info->origin = (buf[17] & 0x20) >> 5;
186 /* FIXME check for valid targa data */
188 return 0;
192 /* decode a frame */
193 static mp_image_t *decode(sh_video_t *sh, void *raw, int len, int flags)
195 TGAInfo *info = sh->context;
196 unsigned char *data = raw;
197 mp_image_t *mpi;
200 if (len <= 0)
201 return NULL; /* skip frame */
203 read_tga_header(data, info); /* read information about the file */
205 if (info->bpp == 24)
206 out_fmt = IMGFMT_BGR24;
207 else if (info->bpp == 32)
208 out_fmt = IMGFMT_BGR32;
209 else
211 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported TGA type! depth=%d\n",info->bpp);
212 return NULL;
215 if (info->img_type != TGA_UNCOMP_TRUECOLOR && info->img_type != TGA_RLE_TRUECOLOR) /* not a true color image */
217 mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Unsupported TGA type: %i!\n", info->img_type);
218 return NULL;
221 /* if img.origin is 0, we decode from bottom to top. if it's 1, we decode from top to bottom */
222 info->start_row = (info->origin) ? 0 : info->height - 1;
223 info->increment = (info->origin) ? 1 : -1;
225 /* set data to the beginning of the image data */
226 data += 18 + info->id_len;
228 /* (re)init libvo if image parameters changed (width/height/colorspace) */
229 if (last_w != info->width || last_h != info->height || last_c != out_fmt)
231 last_w = info->width;
232 last_h = info->height;
233 last_c = out_fmt;
235 if (!out_fmt || !mpcodecs_config_vo(sh, info->width, info->height, out_fmt))
236 return NULL;
239 if (!(mpi = mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, info->width, info->height)))
240 return NULL;
242 /* finally decode the image */
243 if (info->img_type == TGA_UNCOMP_TRUECOLOR)
244 decode_uncompressed_tga(info, data, mpi);
245 else if (info->img_type == TGA_RLE_TRUECOLOR)
246 decode_rle_tga(info, data, mpi);
247 // else
248 // mpi = NULL;
250 return mpi;