ogg_helper.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:7k
源码类别:

Windows CE

开发平台:

C/C++

  1. /* libOggFLAC - Free Lossless Audio Codec + Ogg library
  2.  * Copyright (C) 2004,2005  Josh Coalson
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  *
  8.  * - Redistributions of source code must retain the above copyright
  9.  * notice, this list of conditions and the following disclaimer.
  10.  *
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  * notice, this list of conditions and the following disclaimer in the
  13.  * documentation and/or other materials provided with the distribution.
  14.  *
  15.  * - Neither the name of the Xiph.org Foundation nor the names of its
  16.  * contributors may be used to endorse or promote products derived from
  17.  * this software without specific prior written permission.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20.  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22.  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
  23.  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  27.  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28.  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29.  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30.  */
  31. #include <stdlib.h> /* for malloc() */
  32. #include <string.h> /* for memcmp(), memcpy() */
  33. #include "FLAC/assert.h"
  34. #include "private/ogg_helper.h"
  35. #include "protected/seekable_stream_encoder.h"
  36. static FLAC__bool full_read_(OggFLAC__SeekableStreamEncoder *encoder, FLAC__byte *buffer, unsigned bytes, OggFLAC__SeekableStreamEncoderReadCallback read_callback, void *client_data)
  37. {
  38. while(bytes > 0) {
  39. unsigned bytes_read = bytes;
  40. switch(read_callback(encoder, buffer, &bytes_read, client_data)) {
  41. case OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE:
  42. bytes -= bytes_read;
  43. buffer += bytes_read;
  44. break;
  45. case OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_END_OF_STREAM:
  46. if(bytes_read == 0) {
  47. encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
  48. return false;
  49. }
  50. bytes -= bytes_read;
  51. buffer += bytes_read;
  52. break;
  53. case OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_ABORT:
  54. encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR;
  55. return false;
  56. default:
  57. /* double protection: */
  58. FLAC__ASSERT(0);
  59. encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR;
  60. return false;
  61. }
  62. }
  63. return true;
  64. }
  65. void simple_ogg_page__init(ogg_page *page)
  66. {
  67. page->header = 0;
  68. page->header_len = 0;
  69. page->body = 0;
  70. page->body_len = 0;
  71. }
  72. void simple_ogg_page__clear(ogg_page *page)
  73. {
  74. if(page->header)
  75. free(page->header);
  76. if(page->body)
  77. free(page->body);
  78. simple_ogg_page__init(page);
  79. }
  80. FLAC__bool simple_ogg_page__get_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, OggFLAC__SeekableStreamEncoderSeekCallback seek_callback, OggFLAC__SeekableStreamEncoderReadCallback read_callback, void *client_data)
  81. {
  82. static const unsigned OGG_HEADER_FIXED_PORTION_LEN = 27;
  83. static const unsigned OGG_MAX_HEADER_LEN = 27/*OGG_HEADER_FIXED_PORTION_LEN*/ + 255;
  84. FLAC__byte crc[4];
  85. FLAC__ASSERT(page->header == 0);
  86. FLAC__ASSERT(page->header_len == 0);
  87. FLAC__ASSERT(page->body == 0);
  88. FLAC__ASSERT(page->body_len == 0);
  89. /* move the stream pointer to the supposed beginning of the page */
  90. if(seek_callback(encoder, position, client_data) != FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK) {
  91. encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR;
  92. return false;
  93. }
  94. /* allocate space for the page header */
  95. if(0 == (page->header = (unsigned char *)malloc(OGG_MAX_HEADER_LEN))) {
  96. encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
  97. return false;
  98. }
  99. /* read in the fixed part of the page header (up to but not including
  100.  * the segment table */
  101. if(!full_read_(encoder, page->header, OGG_HEADER_FIXED_PORTION_LEN, read_callback, client_data))
  102. return false;
  103. page->header_len = OGG_HEADER_FIXED_PORTION_LEN + page->header[26];
  104. /* check to see if it's a correct, "simple" page (one packet only) */
  105. if(
  106. memcmp(page->header, "OggS", 4) ||               /* doesn't start with OggS */
  107. (page->header[5] & 0x01) ||                      /* continued packet */
  108. memcmp(page->header+6, "", 8) || /* granulepos is non-zero */
  109. page->header[26] == 0                            /* packet is 0-size */
  110. ) {
  111. encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
  112. return false;
  113. }
  114. /* read in the segment table */
  115. if(!full_read_(encoder, page->header + OGG_HEADER_FIXED_PORTION_LEN, page->header[26], read_callback, client_data))
  116. return false;
  117. {
  118. unsigned i;
  119. /* check to see that it specifies a single packet */
  120. for(i = 0; i < (unsigned)page->header[26] - 1; i++) {
  121. if(page->header[i + OGG_HEADER_FIXED_PORTION_LEN] != 255) {
  122. encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
  123. return false;
  124. }
  125. }
  126. page->body_len = 255 * i + page->header[i];
  127. }
  128. /* allocate space for the page body */
  129. if(0 == (page->body = (unsigned char *)malloc(page->body_len))) {
  130. encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
  131. return false;
  132. }
  133. /* read in the page body */
  134. if(!full_read_(encoder, page->body, page->body_len, read_callback, client_data))
  135. return false;
  136. /* check the CRC */
  137. memcpy(crc, page->header+22, 4);
  138. ogg_page_checksum_set(page);
  139. if(memcmp(crc, page->header+22, 4)) {
  140. encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
  141. return false;
  142. }
  143. return true;
  144. }
  145. FLAC__bool simple_ogg_page__set_at(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 position, ogg_page *page, OggFLAC__SeekableStreamEncoderSeekCallback seek_callback, OggFLAC__SeekableStreamEncoderWriteCallback write_callback, void *client_data)
  146. {
  147. FLAC__ASSERT(page->header != 0);
  148. FLAC__ASSERT(page->header_len != 0);
  149. FLAC__ASSERT(page->body != 0);
  150. FLAC__ASSERT(page->body_len != 0);
  151. /* move the stream pointer to the supposed beginning of the page */
  152. if(seek_callback(encoder, position, client_data) != FLAC__SEEKABLE_STREAM_ENCODER_SEEK_STATUS_OK) {
  153. encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR;
  154. return false;
  155. }
  156. ogg_page_checksum_set(page);
  157. /* re-write the page */
  158. if(write_callback(encoder, page->header, page->header_len, 0, 0, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
  159. encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
  160. return false;
  161. }
  162. return true;
  163. }