home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wvis0626.zip / warpvision_20020626.zip / libmpeg2 / decode.c < prev    next >
C/C++ Source or Header  |  2002-06-19  |  7KB  |  263 lines

  1. /*
  2.  * decode.c
  3.  * Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
  4.  *
  5.  * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
  6.  *
  7.  * mpeg2dec is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 2 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * mpeg2dec is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20.  */
  21.  
  22. #include "config.h"
  23.  
  24. #include <stdio.h>
  25. #include <string.h>    /* memcpy/memset, try to remove */
  26. #include <stdlib.h>
  27. #include <inttypes.h>
  28.  
  29. #include "video_out.h"
  30. #include "mpeg2.h"
  31. #include "mpeg2_internal.h"
  32. #include "mm_accel.h"
  33. #include "attributes.h"
  34. #include "mmx.h"
  35.  
  36. #ifdef HAVE_MEMALIGN
  37. /* some systems have memalign() but no declaration for it */
  38. void * memalign (size_t align, size_t size);
  39. #else
  40. /* assume malloc alignment is sufficient */
  41. #define memalign(align,size) malloc (size)
  42. #endif
  43.  
  44. #define BUFFER_SIZE (224 * 1024)
  45.  
  46. mpeg2_config_t config;
  47.  
  48. void mpeg2_init (mpeg2dec_t * mpeg2dec, uint32_t mm_accel,
  49.          vo_instance_t * output)
  50. {
  51.     static int do_init = 1;
  52.  
  53.     if (do_init) {
  54.     do_init = 0;
  55.     config.flags = mm_accel;
  56.     idct_init ();
  57.     motion_comp_init ();
  58.     }
  59.  
  60.     mpeg2dec->chunk_buffer = memalign (16, BUFFER_SIZE + 4);
  61.     mpeg2dec->picture = memalign (16, sizeof (picture_t));
  62.  
  63.     mpeg2dec->shift = 0xffffff00;
  64.     mpeg2dec->is_sequence_needed = 1;
  65.     mpeg2dec->drop_flag = 0;
  66.     mpeg2dec->drop_frame = 0;
  67.     mpeg2dec->in_slice = 0;
  68.     mpeg2dec->output = output;
  69.     mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
  70.     mpeg2dec->code = 0xb4;
  71.  
  72.     memset (mpeg2dec->picture, 0, sizeof (picture_t));
  73.  
  74.     /* initialize supstructures */
  75.     header_state_init (mpeg2dec->picture);
  76. }
  77.  
  78. static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code,
  79.                    uint8_t * buffer)
  80. {
  81.     picture_t * picture;
  82.     int is_frame_done;
  83.  
  84.     /* wait for sequence_header_code */
  85.     if (mpeg2dec->is_sequence_needed && (code != 0xb3))
  86.     return 0;
  87.  
  88.     stats_header (code, buffer);
  89.  
  90.     picture = mpeg2dec->picture;
  91.     is_frame_done = mpeg2dec->in_slice && ((!code) || (code >= 0xb0));
  92.  
  93.     if (is_frame_done) {
  94.     mpeg2dec->in_slice = 0;
  95.  
  96.     if (((picture->picture_structure == FRAME_PICTURE) ||
  97.          (picture->second_field)) &&
  98.         (!(mpeg2dec->drop_frame))) {
  99.         vo_draw ((picture->picture_coding_type == B_TYPE) ?
  100.              picture->current_frame :
  101.              picture->forward_reference_frame);
  102. #ifdef ARCH_X86
  103.         if (config.flags & MM_ACCEL_X86_MMX)
  104.         emms ();
  105. #endif
  106.     }
  107.     }
  108.  
  109.     switch (code) {
  110.     case 0x00:    /* picture_start_code */
  111.     if (header_process_picture_header (picture, buffer)) {
  112.         fprintf (stderr, "bad picture header\n");
  113.         exit (1);
  114.     }
  115.     mpeg2dec->drop_frame =
  116.         mpeg2dec->drop_flag && (picture->picture_coding_type == B_TYPE);
  117.     break;
  118.  
  119.     case 0xb3:    /* sequence_header_code */
  120.     if (header_process_sequence_header (picture, buffer)) {
  121.         fprintf (stderr, "bad sequence header\n");
  122.         exit (1);
  123.     }
  124.     if (mpeg2dec->is_sequence_needed) {
  125.         mpeg2dec->is_sequence_needed = 0;
  126.         if (vo_setup (mpeg2dec->output, picture->coded_picture_width,
  127.               picture->coded_picture_height)) {
  128.         fprintf (stderr, "display setup failed\n");
  129.         exit (1);
  130.         }
  131.         picture->forward_reference_frame =
  132.         vo_get_frame (mpeg2dec->output,
  133.                   VO_PREDICTION_FLAG | VO_BOTH_FIELDS);
  134.         picture->backward_reference_frame =
  135.         vo_get_frame (mpeg2dec->output,
  136.                   VO_PREDICTION_FLAG | VO_BOTH_FIELDS);
  137.     }
  138.     mpeg2dec->frame_rate_code = picture->frame_rate_code;    /* FIXME */
  139.     break;
  140.  
  141.     case 0xb5:    /* extension_start_code */
  142.     if (header_process_extension (picture, buffer)) {
  143.         fprintf (stderr, "bad extension\n");
  144.         exit (1);
  145.     }
  146.     break;
  147.  
  148.     default:
  149. //    if (code >= 0xb9)
  150. //        fprintf (stderr, "stream not demultiplexed ?\n");
  151.  
  152.     if (code >= 0xb0)
  153.         break;
  154.  
  155.     if (!(mpeg2dec->in_slice)) {
  156.         mpeg2dec->in_slice = 1;
  157.  
  158.         if (picture->second_field)
  159.         vo_field (picture->current_frame, picture->picture_structure);
  160.         else {
  161.         if (picture->picture_coding_type == B_TYPE)
  162.             picture->current_frame =
  163.             vo_get_frame (mpeg2dec->output,
  164.                       picture->picture_structure);
  165.         else {
  166.             picture->current_frame =
  167.             vo_get_frame (mpeg2dec->output,
  168.                       (VO_PREDICTION_FLAG |
  169.                        picture->picture_structure));
  170.             picture->forward_reference_frame =
  171.             picture->backward_reference_frame;
  172.             picture->backward_reference_frame = picture->current_frame;
  173.         }
  174.         }
  175.     }
  176.  
  177.     if (!(mpeg2dec->drop_frame)) {
  178.         slice_process (picture, code, buffer);
  179.  
  180. #ifdef ARCH_X86
  181.         if (config.flags & MM_ACCEL_X86_MMX)
  182.         emms ();
  183. #endif
  184.     }
  185.     }
  186.  
  187.     return is_frame_done;
  188. }
  189.  
  190. static inline uint8_t * copy_chunk (mpeg2dec_t * mpeg2dec,
  191.                     uint8_t * current, uint8_t * end)
  192. {
  193.     uint32_t shift;
  194.     uint8_t * chunk_ptr;
  195.     uint8_t * limit;
  196.     uint8_t byte;
  197.  
  198.     shift = mpeg2dec->shift;
  199.     chunk_ptr = mpeg2dec->chunk_ptr;
  200.     limit = current + (mpeg2dec->chunk_buffer + BUFFER_SIZE - chunk_ptr);
  201.     if (limit > end)
  202.     limit = end;
  203.  
  204.     while (1) {
  205.     byte = *current++;
  206.     if (shift != 0x00000100) {
  207.         shift = (shift | byte) << 8;
  208.         *chunk_ptr++ = byte;
  209.         if (current < limit)
  210.         continue;
  211.         if (current == end) {
  212.         mpeg2dec->chunk_ptr = chunk_ptr;
  213.         mpeg2dec->shift = shift;
  214.         return NULL;
  215.         } else {
  216.         /* we filled the chunk buffer without finding a start code */
  217.         mpeg2dec->code = 0xb4;    /* sequence_error_code */
  218.         mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
  219.         return current;
  220.         }
  221.     }
  222.     mpeg2dec->code = byte;
  223.     mpeg2dec->chunk_ptr = mpeg2dec->chunk_buffer;
  224.     mpeg2dec->shift = 0xffffff00;
  225.     return current;
  226.     }
  227. }
  228.  
  229. int mpeg2_decode_data (mpeg2dec_t * mpeg2dec, uint8_t * current, uint8_t * end)
  230. {
  231.     int ret;
  232.     uint8_t code;
  233.  
  234.     ret = 0;
  235.  
  236.     while (current != end) {
  237.     code = mpeg2dec->code;
  238.     current = copy_chunk (mpeg2dec, current, end);
  239.     if (current == NULL)
  240.         return ret;
  241.     ret += parse_chunk (mpeg2dec, code, mpeg2dec->chunk_buffer);
  242.     }
  243.     return ret;
  244. }
  245.  
  246. void mpeg2_close (mpeg2dec_t * mpeg2dec)
  247. {
  248.     static uint8_t finalizer[] = {0,0,1,0xb4};
  249.  
  250.     mpeg2_decode_data (mpeg2dec, finalizer, finalizer+4);
  251.  
  252.     if (! (mpeg2dec->is_sequence_needed))
  253.     vo_draw (mpeg2dec->picture->backward_reference_frame);
  254.  
  255.     free (mpeg2dec->chunk_buffer);
  256.     free (mpeg2dec->picture);
  257. }
  258.  
  259. void mpeg2_drop (mpeg2dec_t * mpeg2dec, int flag)
  260. {
  261.     mpeg2dec->drop_flag = flag;
  262. }
  263.