Advertisement
Guest User

windows: fixed AVI image size, now it should resize Hi-Res image properly. +

a guest
Jan 29th, 2011
284
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 12.84 KB | None | 0 0
  1. From c7691265db228e760b2076f6c55e351394d25ac9 Mon Sep 17 00:00:00 2001
  2. From: gocha <gochaism@gmail.com>
  3. Date: Sun, 30 Jan 2011 12:43:09 +0900
  4. Subject: [PATCH] windows: fixed AVI image size, now it should resize Hi-Res image properly.
  5.  added GUI.AVIHiRes option, which allows us recording Hi-Res image without down-sampling. (it cannot be changed from GUI at the moment, needs a little more addition in menu/dialog)
  6.  modified ReInitSound, to do nothing during AVI recording (fix "Reset during AVI recording" situation)
  7.  
  8. Note: my AVI recording code doesn't use Convert16To24. I guess it can be simplified like Convert16To32 from now.
  9. ---
  10. win32/wconfig.cpp     |    1 +
  11.  win32/win32.cpp       |  294 +++++++++++++++++++++++++++++++++++++++++--------
  12.  win32/win32_sound.cpp |    5 +-
  13.  win32/wsnes9x.h       |    1 +
  14.  4 files changed, 252 insertions(+), 49 deletions(-)
  15.  
  16. diff --git a/win32/wconfig.cpp b/win32/wconfig.cpp
  17. index 03f97e8..28242ee 100644
  18. --- a/win32/wconfig.cpp
  19. +++ b/win32/wconfig.cpp
  20. @@ -864,6 +864,7 @@ void WinRegisterConfigItems()
  21.     AddUIntC("FilterType", GUI.Scale, 0, filterString);
  22.     AddUIntC("FilterHiRes", GUI.ScaleHiRes, 0, filterString2);
  23.     AddBoolC("BlendHiRes", GUI.BlendHiRes, true, "true to horizontally blend Hi-Res images (better transparency effect on filters that do not account for this)");
  24. +   AddBoolC("AVIHiRes", GUI.AVIHiRes, false, "true to record AVI in Hi-Res scale");
  25.     AddBoolC("ShaderEnabled", GUI.shaderEnabled, false, "true to use pixel shader (if supported by output method)");
  26.     AddStringC("Direct3D:HLSLFileName", GUI.HLSLshaderFileName, MAX_PATH, "", "shader filename for Direct3D mode");
  27.     AddStringC("OpenGL:GLSLFileName", GUI.GLSLshaderFileName, MAX_PATH, "", "shader filename for OpenGL mode (bsnes-style XML shader)");
  28. diff --git a/win32/win32.cpp b/win32/win32.cpp
  29. index cebc8f6..8672d5a 100644
  30. --- a/win32/win32.cpp
  31. +++ b/win32/win32.cpp
  32. @@ -222,11 +222,11 @@ static int avi_sound_bytes_per_sample = 0;
  33.  static int avi_sound_samples_per_update = 0;
  34.  static int avi_width = 0;
  35.  static int avi_height = 0;
  36. +static int avi_pitch = 0;
  37. +static int avi_image_size = 0;
  38.  static uint32 avi_skip_frames = 0;
  39.  static bool pre_avi_soundsync = true;
  40.  static uint32 pre_avi_soundinputrate = 32000;
  41. -//void Convert8To24 (SSurface *src, SSurface *dst, RECT *srect);
  42. -void Convert16To24 (SSurface *src, SSurface *dst, RECT *srect);
  43.  void DoAVIOpen(const char* filename);
  44.  void DoAVIClose(int reason);
  45.  
  46. @@ -1121,6 +1121,221 @@ bool JustifierOffscreen()
  47.  // }
  48.  //}
  49.  
  50. +// Dst: GFX.Screen 256xH  (1x1) 16bpp top-down
  51. +// Src: avi_buffer 256xH  (1x1) 24bpp bottom-up
  52. +void BuildAVIVideoFrame1X (void)
  53. +{
  54. +   const int snesWidth = IPPU.RenderedScreenWidth;
  55. +   const int snesHeight = IPPU.RenderedScreenHeight;
  56. +   const int width = min(snesWidth, avi_width);
  57. +   const int height = min(snesHeight, avi_height);
  58. +   const int pitch = GFX.Pitch;
  59. +#ifdef LSB_FIRST
  60. +   const bool order_is_rgb = (GUI.RedShift < GUI.BlueShift);
  61. +#else
  62. +   const bool order_is_rgb = (GUI.RedShift > GUI.BlueShift);
  63. +#endif
  64. +   const int src_step = pitch - width * 2;
  65. +   const int dst_step = -(avi_pitch + width * 3);
  66. +   const int image_offset = (avi_height - height) * avi_pitch;
  67. +   uint16 *s = GFX.Screen;
  68. +   uint8  *d = &avi_buffer[(avi_height - 1) * avi_pitch];
  69. +
  70. +   for(int y = 0; y < height; y++)
  71. +   {
  72. +       for(int x = 0; x < width; x++)
  73. +       {
  74. +           if(order_is_rgb)
  75. +           {
  76. +               // Order is RGB
  77. +               uint32 pixel = *s++;
  78. +               *(d + 0) = (pixel >> (11 - 3)) & 0xf8;
  79. +               *(d + 1) = (pixel >> (6 - 3)) & 0xf8;
  80. +               *(d + 2) = (pixel & 0x1f) << 3;
  81. +               d += 3;
  82. +           }
  83. +           else
  84. +           {
  85. +               // Order is BGR
  86. +               uint32 pixel = *s++;
  87. +               *(d + 0) = (pixel & 0x1f) << 3;
  88. +               *(d + 1) = (pixel >> (6 - 3)) & 0xf8;
  89. +               *(d + 2) = (pixel >> (11 - 3)) & 0xf8;
  90. +               d += 3;
  91. +           }
  92. +       }
  93. +       s = (uint16*)((uint8*)s + src_step);
  94. +       d += dst_step;
  95. +   }
  96. +
  97. +   // black out what we might have missed
  98. +   if(image_offset > 0)
  99. +       memset(avi_buffer, 0, image_offset);
  100. +}
  101. +
  102. +// Dst: GFX.Screen 256xH  (1x1) 16bpp top-down
  103. +// Src: avi_buffer 512x2H (2x2) 24bpp bottom-up
  104. +void BuildAVIVideoFrame2X (void)
  105. +{
  106. +   const int snesWidth = IPPU.RenderedScreenWidth;
  107. +   const int snesHeight = IPPU.RenderedScreenHeight;
  108. +   const int width = min(snesWidth, avi_width / 2);
  109. +   const int height = min(snesHeight, avi_height / 2);
  110. +   const int pitch = GFX.Pitch;
  111. +#ifdef LSB_FIRST
  112. +   const bool order_is_rgb = (GUI.RedShift < GUI.BlueShift);
  113. +#else
  114. +   const bool order_is_rgb = (GUI.RedShift > GUI.BlueShift);
  115. +#endif
  116. +   const int src_step[2] = { -width * 2, pitch - width * 2 };
  117. +   const int dst_step = -(avi_pitch + width * 3 * 2);
  118. +   const int image_offset = (avi_height - height * 2) * avi_pitch;
  119. +   uint16 *s = GFX.Screen;
  120. +   uint8  *d = &avi_buffer[(avi_height - 1) * avi_pitch];
  121. +
  122. +   for(int y = 0; y < height * 2; y++)
  123. +   {
  124. +       for(int x = 0; x < width; x++)
  125. +       {
  126. +           if(order_is_rgb)
  127. +           {
  128. +               // Order is RGB
  129. +               uint32 pixel = *s++;
  130. +               *(d + 0) = *(d + 3) = (pixel >> (11 - 3)) & 0xf8;
  131. +               *(d + 1) = *(d + 4) = (pixel >> (6 - 3)) & 0xf8;
  132. +               *(d + 2) = *(d + 5) = (pixel & 0x1f) << 3;
  133. +               d += 6;
  134. +           }
  135. +           else
  136. +           {
  137. +               // Order is BGR
  138. +               uint32 pixel = *s++;
  139. +               *(d + 0) = *(d + 3) = (pixel & 0x1f) << 3;
  140. +               *(d + 1) = *(d + 4) = (pixel >> (6 - 3)) & 0xf8;
  141. +               *(d + 2) = *(d + 5) = (pixel >> (11 - 3)) & 0xf8;
  142. +               d += 6;
  143. +           }
  144. +       }
  145. +       s = (uint16*)((uint8*)s + src_step[y % 2]);
  146. +       d += dst_step;
  147. +   }
  148. +
  149. +   // black out what we might have missed
  150. +   if(image_offset > 0)
  151. +       memset(avi_buffer, 0, image_offset);
  152. +}
  153. +
  154. +// Dst: GFX.Screen 512xH  (2x1) 16bpp top-down
  155. +// Src: avi_buffer 256xH  (1x1) 24bpp bottom-up
  156. +void BuildAVIVideoFrame1XHiRes (void)
  157. +{
  158. +   const int snesWidth = IPPU.RenderedScreenWidth;
  159. +   const int snesHeight = IPPU.RenderedScreenHeight;
  160. +   const int width = min(snesWidth / 2, avi_width);
  161. +   const int height = min(snesHeight, avi_height);
  162. +   const int pitch = GFX.Pitch;
  163. +#ifdef LSB_FIRST
  164. +   const bool order_is_rgb = (GUI.RedShift < GUI.BlueShift);
  165. +#else
  166. +   const bool order_is_rgb = (GUI.RedShift > GUI.BlueShift);
  167. +#endif
  168. +   const int src_step = pitch - width * 2 * 2;
  169. +   const int dst_step = -(avi_pitch + width * 3);
  170. +   const int image_offset = (avi_height - height) * avi_pitch;
  171. +   uint16 *s = GFX.Screen;
  172. +   uint8  *d = &avi_buffer[(avi_height - 1) * avi_pitch];
  173. +
  174. +   #define Interp(c1, c2) \
  175. +       (c1 == c2) ? c1 : \
  176. +       (((((c1 & 0x07E0)      + (c2 & 0x07E0)) >> 1) & 0x07E0) + \
  177. +       ((((c1 & 0xF81F)      + (c2 & 0xF81F)) >> 1) & 0xF81F))
  178. +
  179. +   for(int y = 0; y < height; y++)
  180. +   {
  181. +       for(int x = 0; x < width; x++)
  182. +       {
  183. +           if(order_is_rgb)
  184. +           {
  185. +               // Order is RGB
  186. +               uint32 pixel = Interp(s[0],s[1]);
  187. +               s += 2;
  188. +               *(d + 0) = (pixel >> (11 - 3)) & 0xf8;
  189. +               *(d + 1) = (pixel >> (6 - 3)) & 0xf8;
  190. +               *(d + 2) = (pixel & 0x1f) << 3;
  191. +               d += 3;
  192. +           }
  193. +           else
  194. +           {
  195. +               // Order is BGR
  196. +               uint32 pixel = Interp(s[0],s[1]);
  197. +               s += 2;
  198. +               *(d + 0) = (pixel & 0x1f) << 3;
  199. +               *(d + 1) = (pixel >> (6 - 3)) & 0xf8;
  200. +               *(d + 2) = (pixel >> (11 - 3)) & 0xf8;
  201. +               d += 3;
  202. +           }
  203. +       }
  204. +       s = (uint16*)((uint8*)s + src_step);
  205. +       d += dst_step;
  206. +   }
  207. +
  208. +   // black out what we might have missed
  209. +   if(image_offset > 0)
  210. +       memset(avi_buffer, 0, image_offset);
  211. +}
  212. +
  213. +// Dst: GFX.Screen 512xH  (1x1) 16bpp top-down
  214. +// Src: avi_buffer 512x2H (1x2) 24bpp bottom-up
  215. +void BuildAVIVideoFrame2XHiRes (void)
  216. +{
  217. +   const int snesWidth = IPPU.RenderedScreenWidth;
  218. +   const int snesHeight = IPPU.RenderedScreenHeight;
  219. +   const int width = min(snesWidth, avi_width);
  220. +   const int height = min(snesHeight, avi_height / 2);
  221. +   const int pitch = GFX.Pitch;
  222. +#ifdef LSB_FIRST
  223. +   const bool order_is_rgb = (GUI.RedShift < GUI.BlueShift);
  224. +#else
  225. +   const bool order_is_rgb = (GUI.RedShift > GUI.BlueShift);
  226. +#endif
  227. +   const int src_step[2] = { -width * 2, pitch - width * 2 };
  228. +   const int dst_step = -(avi_pitch + width * 3);
  229. +   const int image_offset = (avi_height - height * 2) * avi_pitch;
  230. +   uint16 *s = GFX.Screen;
  231. +   uint8  *d = &avi_buffer[(avi_height - 1) * avi_pitch];
  232. +
  233. +   for(int y = 0; y < height * 2; y++)
  234. +   {
  235. +       for(int x = 0; x < width; x++)
  236. +       {
  237. +           if(order_is_rgb)
  238. +           {
  239. +               // Order is RGB
  240. +               uint32 pixel = *s++;
  241. +               *(d + 0) = (pixel >> (11 - 3)) & 0xf8;
  242. +               *(d + 1) = (pixel >> (6 - 3)) & 0xf8;
  243. +               *(d + 2) = (pixel & 0x1f) << 3;
  244. +               d += 3;
  245. +           }
  246. +           else
  247. +           {
  248. +               // Order is BGR
  249. +               uint32 pixel = *s++;
  250. +               *(d + 0) = (pixel & 0x1f) << 3;
  251. +               *(d + 1) = (pixel >> (6 - 3)) & 0xf8;
  252. +               *(d + 2) = (pixel >> (11 - 3)) & 0xf8;
  253. +               d += 3;
  254. +           }
  255. +       }
  256. +       s = (uint16*)((uint8*)s + src_step[y % 2]);
  257. +       d += dst_step;
  258. +   }
  259. +
  260. +   // black out what we might have missed
  261. +   if(image_offset > 0)
  262. +       memset(avi_buffer, 0, image_offset);
  263. +}
  264. +
  265.  void DoAVIOpen(const TCHAR* filename)
  266.  {
  267.     // close current instance
  268. @@ -1153,12 +1368,20 @@ void DoAVIOpen(const TCHAR* filename)
  269.     avi_height = IPPU.RenderedScreenHeight;
  270.     avi_skip_frames = Settings.SkipFrames;
  271.  
  272. +   if(GUI.AVIHiRes && avi_width <= SNES_WIDTH)
  273. +       avi_width = SNES_WIDTH*2;
  274. +   else if(!GUI.AVIHiRes && avi_width > SNES_WIDTH)
  275. +       avi_width = SNES_WIDTH;
  276.     if(GUI.HeightExtend && avi_height < SNES_HEIGHT_EXTENDED)
  277.         avi_height = SNES_HEIGHT_EXTENDED;
  278. -
  279. +   if(GUI.AVIHiRes)
  280. +       avi_height *= 2;
  281.     if(avi_height % 2 != 0) // most codecs can't handle odd-height images
  282.         avi_height++;
  283.  
  284. +   avi_pitch = ((avi_width * 24 + 31) / 8) & ~3;
  285. +   avi_image_size = avi_pitch * avi_height;
  286. +
  287.     BITMAPINFOHEADER bi;
  288.     memset(&bi, 0, sizeof(bi));
  289.     bi.biSize = 0x28;
  290. @@ -1166,7 +1389,7 @@ void DoAVIOpen(const TCHAR* filename)
  291.     bi.biBitCount = 24;
  292.     bi.biWidth = avi_width;
  293.     bi.biHeight = avi_height;
  294. -   bi.biSizeImage = 3*bi.biWidth*bi.biHeight;
  295. +   bi.biSizeImage = avi_image_size;
  296.  
  297.     AVISetVideoFormat(&bi, GUI.AVIOut);
  298.  
  299. @@ -1196,7 +1419,7 @@ void DoAVIOpen(const TCHAR* filename)
  300.     avi_sound_bytes_per_sample = wfx.nBlockAlign;
  301.  
  302.     // init buffers
  303. -   avi_buffer = new uint8[3*avi_width*avi_height];
  304. +   avi_buffer = new uint8[avi_image_size];
  305.     avi_sound_buffer = new uint8[avi_sound_samples_per_update * avi_sound_bytes_per_sample];
  306.  }
  307.  
  308. @@ -1265,53 +1488,28 @@ void DoAVIVideoFrame(SSurface* source_surface)
  309.     }
  310.  
  311.     // convert to bitdepth 24
  312. -   SSurface avi_dest_surface;
  313. -   RECT full_rect;
  314. -   avi_dest_surface.Surface = avi_buffer;
  315. -   avi_dest_surface.Pitch = avi_width * 3;
  316. -   avi_dest_surface.Width = avi_width;
  317. -   avi_dest_surface.Height = avi_height;
  318. -   full_rect.top = 0;
  319. -   full_rect.left = 0;
  320. -   full_rect.bottom = avi_height;
  321. -   full_rect.right = avi_width;
  322. -   //if(sixteen_bit)
  323. -   //{
  324. -       Convert16To24(source_surface, &avi_dest_surface, &full_rect);
  325. -   //}
  326. -   //else
  327. -   //{
  328. -   //  Convert8To24(source_surface, &avi_dest_surface, &full_rect);
  329. -   //}
  330. -
  331. -   // flip the image vertically
  332. -   const int pitch = 3*avi_width;
  333. -   int y;
  334. -   for(y=0; y<avi_height>>1; ++y)
  335. +   const int snesWidth = IPPU.RenderedScreenWidth;
  336. +   const int snesHeight = IPPU.RenderedScreenHeight;
  337. +   if(snesWidth < SNES_WIDTH*2) // normal
  338.     {
  339. -       uint8* lo_8 = avi_buffer+y*pitch;
  340. -       uint8* hi_8 = avi_buffer+(avi_height-1-y)*pitch;
  341. -       uint32* lo_32=(uint32*)lo_8;
  342. -       uint32* hi_32=(uint32*)hi_8;
  343. -
  344. -       int q;
  345. +       if(avi_width < snesWidth*2) // 1x
  346.         {
  347. -           register uint32 a, b;
  348. -           for(q=pitch>>4; q>0; --q)
  349. -           {
  350. -               a=*lo_32;  b=*hi_32;  *lo_32=b;  *hi_32=a;  ++lo_32;  ++hi_32;
  351. -               a=*lo_32;  b=*hi_32;  *lo_32=b;  *hi_32=a;  ++lo_32;  ++hi_32;
  352. -               a=*lo_32;  b=*hi_32;  *lo_32=b;  *hi_32=a;  ++lo_32;  ++hi_32;
  353. -               a=*lo_32;  b=*hi_32;  *lo_32=b;  *hi_32=a;  ++lo_32;  ++hi_32;
  354. -           }
  355. +           BuildAVIVideoFrame1X();
  356.         }
  357. -
  358. +       else // 2x
  359.         {
  360. -           register uint8 c, d;
  361. -           for(q=(pitch&0x0f); q>0; --q)
  362. -           {
  363. -               c=*lo_8;  d=*hi_8;  *lo_8=d;  *hi_8=c;
  364. -           }
  365. +           BuildAVIVideoFrame2X();
  366. +       }
  367. +   }
  368. +   else // high-res
  369. +   {
  370. +       if(avi_width < snesWidth) // 1x
  371. +       {
  372. +           BuildAVIVideoFrame1XHiRes();
  373. +       }
  374. +       else // 2x
  375. +       {
  376. +           BuildAVIVideoFrame2XHiRes();
  377.         }
  378.     }
  379.  
  380. diff --git a/win32/win32_sound.cpp b/win32/win32_sound.cpp
  381. index 55cae45..ae469b1 100644
  382. --- a/win32/win32_sound.cpp
  383. +++ b/win32/win32_sound.cpp
  384. @@ -218,12 +218,15 @@ returns true if successful, false otherwise
  385.  */
  386.  bool ReInitSound()
  387.  {
  388. +   if (GUI.AVIOut)
  389. +       return false;
  390.     Settings.SoundInputRate = CLAMP(Settings.SoundInputRate,8000, 48000);
  391.     Settings.SoundPlaybackRate = CLAMP(Settings.SoundPlaybackRate,8000, 48000);
  392.     S9xSetSoundMute(GUI.Mute);
  393.     if(S9xSoundOutput)
  394.         S9xSoundOutput->DeInitSoundOutput();
  395. -   return S9xInitSound(GUI.SoundBufferSize,0);
  396. +   bool result = S9xInitSound(GUI.SoundBufferSize,0);
  397. +   return result;
  398.  }
  399.  
  400.  void CloseSoundDevice() {
  401. diff --git a/win32/wsnes9x.h b/win32/wsnes9x.h
  402. index 3273cea..409deed 100644
  403. --- a/win32/wsnes9x.h
  404. +++ b/win32/wsnes9x.h
  405. @@ -301,6 +301,7 @@ struct sGUI {
  406.      RenderFilter Scale;
  407.      RenderFilter ScaleHiRes;
  408.     bool BlendHiRes;
  409. +   bool AVIHiRes;
  410.      bool DoubleBuffered;
  411.      bool FullScreen;
  412.      bool Stretch;
  413. --
  414. 1.7.3.1.msysgit.0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement