ibitstr.cpp
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:12k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* ibitstr.cpp
  2. Input bitstream class implementation
  3.    Changes by Jeff Tsay:
  4. 01/26/96 : Modified for Windows file handles.
  5.    11/29/96 : Added syncword detection for compatibility with streams produced
  6.    by DALET. Changed at the request of Wilfried Solbach, thanks for the
  7.    donation in advance! However Layer I MPP files playback jerkily.
  8.    03/09/97 : Added a routine to read layer III side info. Also not mentioned
  9.    previously are several routines that allow seeking in a stream.
  10.    04/14/97 : Moved the side info routine to the layer III decoder object.
  11.    Revamped the seeking mechanism and also included better syncword detection.
  12.    Moved the original file reading mechanisms back for better
  13.    portability, and used John Fehr's implementations of the seeking routines
  14. for non-Win32 file reading. */
  15. /*
  16.  *  @(#) ibitstream.cc 1.8, last edit: 6/15/94 16:51:45
  17.  *  @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
  18.  *  @(#) Berlin University of Technology
  19.  *
  20.  *  This program is free software; you can redistribute it and/or modify
  21.  *  it under the terms of the GNU General Public License as published by
  22.  *  the Free Software Foundation; either version 2 of the License, or
  23.  *  (at your option) any later version.
  24.  *
  25.  *  This program is distributed in the hope that it will be useful,
  26.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  27.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  28.  *  GNU General Public License for more details.
  29.  *
  30.  *  You should have received a copy of the GNU General Public License
  31.  *  along with this program; if not, write to the Free Software
  32.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  33.  */
  34. /*
  35.  *  Changes from version 1.1 to 1.2:
  36.  *    - third argument in open syscall added
  37.  *    - minor bug in get_header() fixed
  38.  */
  39. #define __WIN32__
  40. #ifdef  __WIN32__
  41. #include <windows.h>
  42. #else
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <unistd.h>
  46. #include <errno.h>
  47. #include <fcntl.h>
  48. #endif   // __WIN32__
  49. #ifndef  GUI
  50. #include <iostream.h>
  51. #endif   // GUI
  52. #include "all.h"
  53. #include "ibitstr.h"
  54. #include "header.h"
  55. #ifdef  DAMN_INTEL_BYTE_ORDER
  56. #define swap_int32(int_32) (((int_32) << 24) | (((int_32) << 8) & 0x00ff0000) | 
  57.                (((int_32) >> 8) & 0x0000ff00) | ((int_32) >> 24))
  58. #endif  // DAMN_INTEL_BYTE_ORDER
  59. Ibitstream::Ibitstream(const char *filename)
  60. {
  61. #ifdef __WIN32__
  62.   SECURITY_ATTRIBUTES security;
  63.   security.nLength              = sizeof(SECURITY_ATTRIBUTES);
  64.   security.lpSecurityDescriptor = NULL;
  65.   security.bInheritHandle       = FALSE;
  66.   fd = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ,
  67.                   &security, OPEN_EXISTING, NULL, NULL);
  68.   if (fd == INVALID_HANDLE_VALUE) {
  69.      char bad_file_msg[256];
  70.      lstrcpy(bad_file_msg, "Error opening file: ");
  71. #ifdef WIN32GUI
  72.   MessageBox(NULL, lstrcat(bad_file_msg, filename) , "Invalid handle", MB_OK);
  73. #else
  74. cerr  << "Error opening file: " << filename << endl;
  75. #endif // WIN32GUI
  76.      return;
  77.   }
  78. #else
  79.   // copy any arguments you need, open the file, and check for error
  80.   if ((fd = open(filename, O_RDONLY)) == -1)
  81.   {
  82. #ifndef GUI
  83.    cerr << "Error opening file: " << filename << endl;
  84. #endif
  85.       return;
  86.   }
  87. #endif // __WIN32__
  88.   wordpointer       = buffer;
  89.   bitindex          = 0;
  90.   // Seeking variables
  91.   current_frame_number = -1;
  92. #ifdef SEEK_STOP
  93.   last_frame_number    = -1;
  94. #endif
  95.   copy = false;
  96. }
  97. Ibitstream::Ibitstream(const Ibitstream &s0)
  98. {
  99.   int32 i;
  100.   fd = s0.fd;
  101.   for (i=0; i<bufferintsize; i++)
  102.       buffer[i] = s0.buffer[i];
  103.   framesize = s0.framesize;
  104.   wordpointer = buffer + (s0.wordpointer - s0.buffer);
  105.   bitindex = s0.bitindex;
  106.   syncword = s0.syncword;
  107.   single_ch_mode = s0.single_ch_mode;
  108.   current_frame_number = s0.current_frame_number;
  109. #ifdef SEEK_STOP
  110.   last_frame_number = s0.last_frame_number;
  111. #endif
  112.   copy = true;
  113. }
  114. // Dummy constructor
  115. Ibitstream::Ibitstream()
  116. {
  117.   fd = 0;
  118.   wordpointer       = buffer;
  119.   bitindex          = 0;
  120.   current_frame_number = -1;
  121. #ifdef SEEK_STOP
  122.   last_frame_number    = -1;
  123. #endif
  124.   copy = false;
  125. }
  126. void Ibitstream::reset()
  127. {
  128.   
  129.   SetFilePointer(fd, 0, NULL, FILE_BEGIN);
  130.   wordpointer       = buffer;
  131.   bitindex          = 0;
  132.   current_frame_number = -1;
  133. #ifdef SEEK_STOP
  134.   last_frame_number    = -1;
  135. #endif
  136.   copy = false;
  137. }
  138. Ibitstream::~Ibitstream()
  139. {
  140.   // close the file
  141. #ifdef __WIN32__
  142.   if (fd && !copy) CloseHandle(fd);
  143. #else
  144.   if (fd && !copy) close(fd);
  145. #endif
  146. }
  147. Ibitstream &Ibitstream::operator = (const Ibitstream &s0)
  148. {
  149.   int32 i;
  150.   fd = s0.fd;
  151.   for (i=0; i<bufferintsize; i++)
  152.       buffer[i] = s0.buffer[i];
  153.   framesize = s0.framesize;
  154.   wordpointer = buffer + (s0.wordpointer - s0.buffer);
  155.   bitindex = s0.bitindex;
  156.   syncword = s0.syncword;
  157.   single_ch_mode = s0.single_ch_mode;
  158.   current_frame_number = s0.current_frame_number;
  159. #ifdef SEEK_STOP
  160.   last_frame_number = s0.last_frame_number;
  161. #endif
  162. copy = true;
  163. return *this;
  164. }
  165. bool Ibitstream::get_header (uint32 *headerstring, enum e_syncmode syncmode)
  166. {
  167.   bool result, sync;
  168.   int32 numread;
  169.   do {
  170. // Read 4 bytes from the file, placing the number of bytes actually
  171.    // read in numread
  172. #ifdef __WIN32__
  173.    result = (bool) ReadFile(fd, (char *) headerstring, 4,
  174.         (DWORD *) &numread, NULL);
  175. #else
  176. if (fd == -1) return false; // check for error opening file
  177. result = (bool) ((numread=read(fd, (char*) headerstring, 4)) == 4);
  178. #endif
  179.    if (!(result && (numread == 4)))
  180.       return false;
  181. #ifdef DAMN_INTEL_BYTE_ORDER
  182. if (syncmode == INITIAL_SYNC) {
  183.    sync =  ((*headerstring & 0x0000F0FF) == 0x0000F0FF);
  184.    } else {
  185.     sync =  ((*headerstring & 0x000CF8FF) == syncword) &&
  186.              (((*headerstring & 0xC0000000) == 0xC0000000) == single_ch_mode);
  187.    }
  188. #else
  189. if (syncmode == INITIAL_SYNC) {
  190. sync =  ((*headerstring & 0xFFF00000) == 0xFFF00000);
  191. } else {
  192.     sync =  ((*headerstring & 0xFFF80C00) == syncword) &&
  193.              (((*headerstring & 0x000000C0) == 0x000000C0) == single_ch_mode);
  194.    }
  195. #endif // DAMN_INTEL_BYTE_ORDER
  196.    if (!sync)
  197.   // rewind 3 bytes in the file so we can try to sync again, if
  198.    // successful set result to true
  199. #ifdef __WIN32__
  200.       result = (bool) SetFilePointer(fd, -3, NULL, FILE_CURRENT);
  201. #else
  202. result = (bool) (lseek(fd, -3, SEEK_CUR) != -1);
  203. #endif // __WIN32__
  204.   } while (!sync && result);
  205.   if (!result)
  206.      return false;
  207. #ifdef DAMN_INTEL_BYTE_ORDER
  208.   uint32 header = *headerstring;
  209.   *headerstring = swap_int32(header);
  210. #endif // DAMN_INTEL_BYTE_ORDER
  211.   current_frame_number++;
  212. #ifdef SEEK_STOP
  213.   if (last_frame_number < current_frame_number)
  214.   last_frame_number = current_frame_number;
  215. #endif
  216.   return true;
  217. }
  218. bool Ibitstream::read_frame(uint32 bytesize)
  219. {
  220.   int32 numread;
  221.   // read bytesize bytes from the file, placing the number of bytes
  222.   // actually read in numread and setting result to true if
  223.   // successful
  224. #ifdef __WIN32__
  225.   bool result = ReadFile(fd, buffer, bytesize, (DWORD *) &numread, NULL);
  226. #else
  227.   bool result = (bool) ((numread=read(fd,buffer,bytesize)) != -1);
  228. #endif // __WIN32__
  229. /*  if (bytesize > (bufferintsize << 2))
  230.   {
  231.  cerr << "Internal error: framelength > bufferlength?!n";
  232.  exit (1);
  233.   } */
  234.   wordpointer = buffer;
  235.   bitindex    = 0;
  236.   framesize   = bytesize;
  237. #ifdef DAMN_INTEL_BYTE_ORDER
  238.   uint32 *wordp;
  239.   for (wordp = buffer + ((bytesize - 1) >> 2); wordp >= buffer; --wordp)
  240.   {
  241. #ifdef INTEL386
  242.   // inline 386 assembly doesn't work on Borland compiler
  243.   __asm {
  244.       mov eax, wordp
  245. mov ebx, [eax]
  246.       bswap ebx
  247.       mov [eax], ebx
  248.   }
  249. #else
  250.  uint32 word   = *wordp;
  251.     *wordp = swap_int32(word);
  252. #endif // INTEL386
  253.   } // for (wordp ...
  254. #endif // DAMN_INTEL_BYTE_ORDER
  255.   return((bool) (result && (numread == framesize)));
  256. }
  257. uint32 Ibitstream::get_bits(uint32 number_of_bits)
  258. {
  259.   static uint32 bitmask[18] =
  260.   {
  261.  0, // dummy
  262.  0x00000001, 0x00000003, 0x00000007, 0x0000000F,
  263.  0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
  264.  0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
  265.  0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
  266.     0x0001FFFF
  267.   };
  268.   uint32 returnvalue;
  269.   uint32 sum = bitindex + number_of_bits;
  270.   if (sum <= 32)
  271.   {
  272.  // all bits contained in *wordpointer
  273.  returnvalue = (*wordpointer >> (32 - sum)) & bitmask[number_of_bits];
  274.  if ((bitindex += number_of_bits) == 32)
  275.  {
  276. bitindex = 0;
  277. /* if ((char *)++wordpointer > (char *)buffer + framesize)
  278. {
  279. cerr << "Ibitstream::get_bits(): no more bits in buffer!n";
  280. exit (1);
  281. } */
  282. wordpointer++; // added by me!
  283.  }
  284.  return returnvalue;
  285.   }
  286. #ifdef DAMN_INTEL_BYTE_ORDER
  287.   *((int16 *)&returnvalue + 1) = *(int16 *)wordpointer;
  288.   wordpointer++; // Added by me!
  289.   *(int16 *)&returnvalue = *((int16 *)wordpointer + 1);
  290. #else
  291.   *(int16 *)&returnvalue = *((int16 *)wordpointer + 1);
  292.   wordpointer++; // Added by me!
  293.   *((int16 *)&returnvalue + 1) = *(int16 *)wordpointer;
  294. #endif // DAMN_INTEL_BYTE_ORDER
  295.   returnvalue >>= 48 - sum; // returnvalue >>= 16 - (number_of_bits - (32 - bitindex))
  296.   returnvalue &= bitmask[number_of_bits];
  297.   bitindex = sum - 32;
  298.   return returnvalue;
  299. }
  300. void Ibitstream::set_syncword(uint32 syncword0)
  301. {
  302. #ifdef DAMN_INTEL_BYTE_ORDER
  303.    syncword = swap_int32(syncword0 & 0xFFFFFF3F);
  304. #else
  305. syncword = syncword0 & 0xFFFFFF3F;
  306. #endif // DAMN_INTEL_BYTE_ORDER
  307.    single_ch_mode = ((syncword0 & 0x000000C0) == 0x000000C0);
  308. }
  309. uint32 Ibitstream::file_size() const
  310. // return the file size of the file
  311. {
  312. #ifdef __WIN32__
  313. return GetFileSize(fd, NULL);
  314. #else
  315. // hmm. I think this should work  -- John Fehr
  316. off_t o_off;
  317. off_t len;
  318. o_off = lseek(fd, 0, SEEK_CUR);
  319. len   = lseek(fd, 0, SEEK_END);
  320. lseek(fd, o_off, SEEK_SET);
  321. return len;
  322. #endif // __WIN32__
  323. }
  324. uint32 Ibitstream::file_pos() const
  325. {
  326. return SetFilePointer(fd, 0, NULL, FILE_CURRENT);
  327. }
  328. #ifdef SEEK_STOP
  329. bool Ibitstream::seek(int32 frame, int32 frame_size)
  330. // set the file pointer to frame * (frame_size + 4) bytes after the
  331. // beginning of the file and return true if successful
  332. {
  333. current_frame_number = frame - 1;
  334. #ifdef __WIN32__
  335. return(SetFilePointer(fd, frame * (frame_size + 4), NULL, FILE_BEGIN)
  336.         != 0xFFFFFFFF);
  337. #else
  338. return lseek(fd, frame * (frame_size + 4), SEEK_SET);
  339. #endif // __WIN32__
  340. }
  341. bool Ibitstream::seek_pad(int32 frame, int32 base_frame_size,
  342.                           Header *header, uint32 *offset)
  343. {
  344. // base_frame_size is the frame size _without_ padding.
  345. Crc16 *crc = NULL;
  346. int32 total_frame_size = base_frame_size + 4;
  347. int32 diff;
  348. if (last_frame_number < frame) {
  349. diff = (last_frame_number >= 0) ?  offset[last_frame_number] : 0;
  350.     // set the file pointer to ((last_frame_number+1) * total_frame_size)
  351.       // bytes after the beginning of the file
  352. #ifdef __WIN32__
  353. SetFilePointer(fd, (last_frame_number + 1) * total_frame_size +
  354. diff, NULL, FILE_BEGIN);
  355. #else
  356. lseek(fd, (last_frame_number + 1) * total_frame_size + diff, SEEK_SET);
  357. #endif // __WIN32__
  358. current_frame_number = last_frame_number;
  359. do {
  360. if (!header->read_header(this, &crc)) // will increment last_frame_number
  361. return false;
  362. } while (last_frame_number < frame);
  363.       return true;
  364. } else {
  365. diff = (frame > 0) ? offset[frame - 1] : 0;
  366.     // set the file pointer to (frame * total_frame_size  + diff) bytes
  367.       // after the beginning of the file
  368. #ifdef __WIN32__
  369. SetFilePointer(fd, frame * total_frame_size + diff, NULL, FILE_BEGIN);
  370. #else
  371. lseek(fd, frame * total_frame_size + diff, SEEK_SET);
  372. #endif // __WIN32__
  373. current_frame_number = frame - 1;
  374.       return header->read_header(this, &crc);
  375. }
  376. }
  377. #endif // SEEK_STOP