1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
/*********************************************************************************
Filename : rgbplayer.c
Desc : This file use SDL library to display the RGB(565) pData.
Its a opensource file
Dependency: Intented to run on LINUX/UNIX based system. It needs SDL.h (which is generally
available at /usr/include/SDL)
if not available please download SDL library from http://sdl.beuc.net/sdl.wiki/FrontPage
Documentation for SDL APIs are also available there.
Usage : rgbplayer
Building : Makefile is provided with the source code.
$make - will build the binary "rgbplayer",
copy the binary to ~/bin/ and change its mode to executable
and delete binary from present directory.
$make clean - will delete the binary from ~/bin directory.
Notes : default frame rate is set to 10 FPS can be changed accordingly
by changing LINE 105 - SDL_Delay(100);
Author : EteRniTy aka Tirtha Kanti Ghosh ([email protected])
Date : 09/11/2009
**********************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>

#include "SDL/SDL.h"
#define RMASK 0
#define GMASK 0
#define BMASK 0
#define AMASK 0

#define MAX_STR_LEN						512

#define FOUR							(4)
#define ALIGN_TO_FOUR(VAL)				(((VAL) + FOUR - 1) & ~(FOUR - 1) )


int GetSizeFromArg(char *arg, int *pWidth, int *pHeight)
{
	char temp[MAX_STR_LEN], tempNum[MAX_STR_LEN];
	unsigned int iCross;
	
	strncpy(&temp[0], arg, MAX_STR_LEN);
	
	
	for(iCross = 0; strlen(&temp[0]); iCross++){
		if('x' == temp[iCross])
			break;
	}
	
	if(strlen(&temp[0]) == iCross)
	{
		printf("error : format should be widthxheight\n");
		return -1;
	}
		
	if( 0 == iCross)
	{
		printf("error : no width input \n");
		return -1;
	}
		
	if( strlen(&temp[0]) - 1 == iCross)
	{
		printf("error : no height input \n");
		return -1;
	}
	
	memcpy(&tempNum[0], &temp[0], iCross);
	tempNum[iCross]	 = 0;
	
	*pWidth = atoi(&tempNum[0]);
						
	memset(&tempNum[0], 0, MAX_STR_LEN);
	
	memcpy(&tempNum[0], &temp[iCross + 1], strlen(&temp[0]) - iCross - 1);
	tempNum[strlen(&temp[0]) - iCross - 1]	 = 0;
	
	*pHeight = atoi(&tempNum[0]);										
		
	return 0;
				
}/*GetSizeFromArg*/

int AlignFourfread(unsigned char *pDst, int width, int height, FILE *fp)
{	
	unsigned int j;
	unsigned int len;
	unsigned char *pMovDst;
	
	pMovDst = pDst;
	j = 0;
	
	while(j < height)
	{
		len = fread(pMovDst, 1, width, fp);
		if(len == 0)
			return j*width;
		pMovDst += 	ALIGN_TO_FOUR(width);
		j++;		
	}/*while*/
	
	return width*height;
}/*AlignFourRead*/
 


static struct option main_options[] = 
{
	{ "input",  required_argument, NULL, 'i' },
	{ "bpp",  required_argument, NULL, 'b' },	
	{ "size",  required_argument, NULL, 's' },	
	{ "interval",  required_argument, NULL, 't' },	
	{ 0, 0, 0, 0}
};


int main(int argc, char *argv[])
{
	
	SDL_Surface *screen; //This pointer will reference the drawing screen	
	SDL_Rect dest; //The destination region of our blit
	int width, height;
	int bpp;
	int intervalTime;	
	
	int opt;
	
	char inputFileName[MAX_STR_LEN];
	char *pData;
	FILE *fp;

	snprintf(&inputFileName[0], MAX_STR_LEN, "out.raw");	
	
	bpp = 32;
	width = 704; height = 480;
	intervalTime = 25;
	
	while ((opt = getopt_long(argc, argv, "i:b:s:t:", 
		main_options, NULL)) != -1) 
	{
		switch(opt) 
		{
			case 'i':
				snprintf(&inputFileName[0], MAX_STR_LEN, "%s", optarg);				
					
			break;
			
			case 'b':
				bpp = atoi(optarg);
			break;
			
			case 's':
				GetSizeFromArg(optarg, &width, &height);						
			break;
					
			case 't':
				intervalTime = atoi(optarg);
				
			break;
						
			default:
				return -1;
			break;
		}/*switch*/
	}/*while opt = getopt_long*/
	
	if(ALIGN_TO_FOUR(width) != width)	
		printf("WARNING : width is not multiply of 4, render may be wrong !\n");		
	
	fp = fopen(&inputFileName[0], "rb");	
	if(NULL == fp)
	{
		printf("Error : File %s could not found\n", &inputFileName[0]);				
		return -1;
	}
	fclose(fp);
				
	
	pData = (char *)malloc(ALIGN_TO_FOUR(width*bpp/8)*height);
	
	printf("%s file contains raw pData with resolution %dx%d  %dbpp\n",
		&inputFileName[0], width, height, bpp);
	
	//We must first initialize the SDL video component, and check for success
	if (SDL_Init(SDL_INIT_VIDEO) != 0) 
	{
		printf("Unable to initialize SDL: %s\n", SDL_GetError());
		return -1;
	}/*if*/	
	
	//When this program exits, SDL_Quit must be called
	atexit(SDL_Quit);	


	//Set the video mode to 640x480 with 16bit colour
	screen = SDL_SetVideoMode(width, height, bpp, 
		SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_ANYFORMAT);		
	
	if (screen == NULL) {
		printf("Unable to set video mode: %s\n", SDL_GetError());		
		SDL_Quit();
		return -1;
	}/*if screen == NULL*/
	
	fp = fopen(&inputFileName[0], "rb");	
	
	if(12 == bpp)/*yv12*/
	{
		SDL_Overlay *overlay; 
		
		overlay = SDL_CreateYUVOverlay(width, height, SDL_YV12_OVERLAY, screen);		 	
		 
		dest.x = 0; dest.y  = 0;
		dest.w = width;
		dest.h = height;
		
		while(1)
		{
			unsigned int len;
			
			SDL_LockSurface(screen);
			SDL_LockYUVOverlay(overlay);
        	        	
			len = AlignFourfread(overlay->pixels[0], width, height, fp);
			if(0 == len)
				break;			
			len = AlignFourfread(overlay->pixels[2], width/2, height/2, fp);
			if(0 == len)
				break;		
			len = AlignFourfread(overlay->pixels[1], width/2, height/2, fp);
			if(0 == len)
				break;			
				
			SDL_UnlockYUVOverlay(overlay);
			SDL_UnlockSurface(screen);
				
			SDL_UpdateRects(screen, 1, &dest);
			SDL_DisplayYUVOverlay(overlay, &dest);	
			
			SDL_Delay(intervalTime);
		}/*while*/
		
		 SDL_FreeYUVOverlay(overlay);
	}
	else
	{
		while( fread(pData,1, ALIGN_TO_FOUR(width*bpp/8)*height, fp) )
		{
			// Create the temp surface from the raw RGB pData
			SDL_Surface *image; //This pointer will reference our bitmap sprite
			SDL_Surface *temp; //This pointer will temporarily reference the pData (checker board)
			
			temp = SDL_CreateRGBSurfaceFrom(pData, width, height, bpp, ALIGN_TO_FOUR(width*bpp/8), 
				RMASK, GMASK, BMASK, AMASK);		
				
			if (temp == NULL) 
			{
				printf("Unable to load checkImage: %s\n", SDL_GetError());
				return 1;
			}/*NULL == temp*/
			
			//Convert the surface to the appropriate display format
			image = SDL_DisplayFormat(temp);
			//Release the temporary surface
			SDL_FreeSurface(temp);
			
			//Construct the destination rectangle for our blit
		//	dest.x = 100; //Display the image at the (X,Y) coordinates (100,100)
		//	dest.y = 100;
			dest.x = 0; dest.y  = 0;
			dest.w = image->w;
			dest.h = image->h;
			//Blit the image to the screen. Important will actually shows the surface on the screen
			SDL_BlitSurface(image, NULL, screen, &dest);
			//Update the part of the screen that changed
			SDL_UpdateRects(screen, 1, &dest);
			//Wait for 100ms (~10 FPS) so we can see the image
			SDL_Delay(intervalTime);
			//Release the surface
			SDL_FreeSurface(image);
		}
	}/*if 12 == bpp*/
	
	fclose(fp);
		
	SDL_Quit();
	  
	return 0;
}