decode.c
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:6k
源码类别:

DVD

开发平台:

Unix_Linux

  1. /*
  2.  *  decode.c
  3.  *
  4.  *  Copyright (C) Aaron Holtzman <aholtzma@ess.engr.uvic.ca> - Nov 1999
  5.  *
  6.  *  Decodes an MPEG-2 video stream.
  7.  *
  8.  *  This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
  9.  *
  10.  *  mpeg2dec 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, or (at your option)
  13.  *  any later version.
  14.  *   
  15.  *  mpeg2dec 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.
  19.  *   
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with GNU Make; see the file COPYING.  If not, write to
  22.  *  the Free Software Foundation, 
  23.  *
  24.  */
  25.  
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <unistd.h>
  29. #include <fcntl.h>
  30. #include <errno.h>
  31. #include "config.h"
  32. #include "old_crap.h"
  33. #include "mpeg2.h"
  34. #include "mpeg2_internal.h"
  35. #include "mb_buffer.h"
  36. #include "motion_comp.h"
  37. #include "bitstream.h"
  38. #include "idct.h"
  39. #include "parse.h"
  40. #include "display.h"
  41. #include "inv_quantize.h"
  42. //this is where we keep the state of the decoder
  43. static picture_t picture;
  44. static slice_t slice;
  45. static macroblock_t *mb;
  46. //global config struct
  47. mpeg2_config_t config;
  48. static uint_32 is_display_initialized = 0;
  49. static uint_32 is_sequence_needed = 1;
  50. static void find_next_start_code()
  51. {
  52. uint_32 code;
  53. bitstream_byte_align();
  54.   while ((code = bitstream_show(24))!=0x01L)
  55. {
  56. //fprintf(stderr,"tried %08xn",code);
  57.     Flush_Buffer(8);
  58. }
  59. }
  60. //find a picture header and parse anything else we happen to find 
  61. //on the way
  62. //FIXME this is crap
  63. uint_32
  64. decode_find_header(uint_32 type,picture_t *picture)
  65. {
  66. uint_32 code;
  67. while(1)
  68. {
  69. //printf("looking for %08xn",type);
  70. // look for next_start_code 
  71. find_next_start_code();
  72. code = bitstream_get(32);
  73. //we found the header we're looking for
  74. if(code == type)
  75. return code;
  76. //we're looking for a slice header 
  77. if(code <= SLICE_START_CODE_MAX && code >= SLICE_START_CODE_MIN &&
  78. type == SLICE_START_CODE_MIN)
  79. return code;
  80. //deal with the header otherwise
  81. switch (code)
  82. {
  83. case GROUP_START_CODE:
  84. parse_gop_header(picture);
  85. break;
  86. case USER_DATA_START_CODE:
  87. parse_user_data();
  88. break;
  89. case EXTENSION_START_CODE:
  90. parse_extension(picture);
  91. break;
  92. //FIXME add in the other strange extension headers
  93. default:
  94. // fprintf(stderr,"Unsupported header 0x%08xn",code);
  95. }
  96. }
  97. }
  98. static void decode_flush_buffer(void)
  99. {
  100. mb_buffer_t mb_buffer;
  101. mb_buffer_flush(&mb_buffer);
  102. idct(&mb_buffer);
  103. motion_comp(&picture,&mb_buffer);
  104. //reset mb pointer for next slice
  105. mb = mb_buffer.macroblocks;
  106. }
  107. void
  108. mpeg2_init(void)
  109. {
  110. uint_32 frame_size;
  111. //FIXME this should go somewhere after we discover how big
  112. //the frame is, or size it so that it will be big enough for
  113. //all cases
  114. frame_size = 720 * 576;
  115. picture.current_frame[0] = malloc(frame_size);
  116. picture.current_frame[1] = malloc(frame_size / 4);
  117. picture.current_frame[2] = malloc(frame_size / 4);
  118. //FIXME setup config properly
  119. config.flags = MPEG2_MMX_ENABLE;
  120. //intialize the decoder state (ie the parser knows best)
  121. parse_state_init(&picture);
  122. idct_init();
  123. motion_comp_init();
  124. mb = mb_buffer_init(CHROMA_420);
  125. }
  126. uint_32 frame_counter = 0;
  127. void
  128. mpeg2_decode(void) 
  129. {
  130. uint_32 mba;      //macroblock address
  131. uint_32 last_mba; //last macroblock in frame
  132. uint_32 mba_inc;
  133. uint_32 mb_width;
  134. uint_32 code;
  135. uint_32 i;
  136. //
  137. //decode one frame
  138. //
  139. //
  140. if(is_sequence_needed)
  141. {
  142. decode_find_header(SEQUENCE_HEADER_CODE,&picture);
  143. parse_sequence_header(&picture);
  144. is_sequence_needed = 0;
  145. }
  146. decode_find_header(PICTURE_START_CODE,&picture);
  147. parse_picture_header(&picture);
  148. //XXX We only do I-frames now
  149. if( picture.picture_coding_type != I_TYPE) 
  150. return;
  151. last_mba = ((picture.coded_picture_height * picture.coded_picture_width) >> 8) - 1;
  152. mb_width = picture.coded_picture_width >> 4;
  153. //we can't initialize the display until we know how big the picture is
  154. if(!is_display_initialized)
  155. {
  156. display_init(picture.coded_picture_width,picture.coded_picture_height);
  157. is_display_initialized = 1;
  158. }
  159. do
  160. {
  161. //find a slice start
  162. code = decode_find_header(SLICE_START_CODE_MIN,&picture);
  163. mba = ((code &0xff) - 1) * mb_width - 1;
  164. //printf("starting mba %d of %d  mbwidth=%dn",mba,last_mba,mb_width);
  165. parse_slice_header(&picture,&slice);
  166. do
  167. {
  168. mba_inc = Get_macroblock_address_increment();
  169. if(mba_inc > 1)
  170. for(i=0; i< mba_inc - 1; i++)
  171. {
  172. mb->skipped = 1;
  173. mb->mba = ++mba;
  174. mb = mb_buffer_increment();
  175. }
  176. mb->skipped = 0;
  177. mb->mba = ++mba; 
  178. parse_macroblock(&picture,&slice,mb);
  179. mb = mb_buffer_increment();
  180. if(!mb)
  181. decode_flush_buffer();
  182. }
  183. while(bitstream_show(23));
  184. }
  185. while(mba < last_mba);
  186. decode_flush_buffer();
  187. display_frame(picture.current_frame);
  188. if(bitstream_show(32) == SEQUENCE_END_CODE)
  189. is_sequence_needed = 1;
  190. printf("frame_counter = %dn",frame_counter++);
  191. }
  192. uint_32 buf[2048/4];
  193. FILE *in_file;
  194.  
  195. void fill_buffer(uint_32 **start,uint_32 **end)
  196. {
  197. uint_32 bytes_read;
  198. bytes_read = fread(buf,1,2048,in_file);
  199. *start = buf;
  200. *end   = buf + bytes_read/4;
  201. if(bytes_read != 2048)
  202. exit(1);
  203. }
  204. int main(int argc,char *argv[])
  205. {
  206. if(argc < 2)
  207. {
  208. fprintf(stderr,"usage: %s video_streamn",argv[0]);
  209. exit(1);
  210. }
  211. printf(PACKAGE"-"VERSION" (C) 1999 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>n");
  212. if(argv[1][0] != '-')
  213. {
  214. in_file = fopen(argv[1],"r");
  215. if(!in_file)
  216. {
  217. fprintf(stderr,"%s - Couldn't open file ",argv[1]);
  218. perror(0);
  219. exit(1);
  220. }
  221. }
  222. else
  223. in_file = stdin;
  224. bitstream_init(fill_buffer);
  225. //FIXME this doesn't go here later
  226. mpeg2_init();
  227. while(1)
  228. mpeg2_decode();
  229.   return 0;
  230. }