home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 June / ccd0605.iso / LINUX / gopchop-1.1.7.tar.tar / gopchop-1.1.7.tar / gopchop-1.1.7 / src / MPEG2Parser.cpp < prev    next >
C/C++ Source or Header  |  2005-05-02  |  34KB  |  1,259 lines

  1. /*
  2. #
  3. # Implements the structure-parsing routines needs to parse an MPEG2 using
  4. # the Parser class memory-management interface.
  5. #
  6. # $Id: MPEG2Parser.cpp,v 1.40 2005/05/02 04:45:57 keescook Exp $
  7. #
  8. # Copyright (C) 2001-2003 Kees Cook
  9. # kees@outflux.net, http://outflux.net/
  10. # This program is free software; you can redistribute it and/or
  11. # modify it under the terms of the GNU General Public License
  12. # as published by the Free Software Foundation; either version 2
  13. # of the License, or (at your option) any later version.
  14. # This program is distributed in the hope that it will be useful,
  15. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. # GNU General Public License for more details.
  18. # You should have received a copy of the GNU General Public License
  19. # along with this program; if not, write to the Free Software
  20. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  21. # http://www.gnu.org/copyleft/gpl.html
  22. #
  23. */
  24.  
  25. #include "GOPchop.h"
  26.  
  27. #include "MPEG2Parser.h"
  28. #include "ElementStream.h"
  29. #include "Picture.h"
  30. #include "mpeg2consts.h"
  31.  
  32. #include "FirstPack.h"
  33.  
  34. // send packet info to stderr
  35. #undef MPEG2_PARSE_TO_STDERR
  36. // write maps to disk
  37. #undef MPEG2_MAP
  38. // write debugging to disk (you don't want this)
  39. #undef MPEG2_DEBUG
  40.  
  41. #if defined(MPEG2_MAP) || defined(MPEG2_DEBUG)
  42. # define MPEG2_DUMP
  43. #endif
  44.  
  45. #ifdef MPEG2_DUMP
  46. FILE *report;
  47. #endif
  48.  
  49. #define WRITE_OUT(t, s...)    fprintf(report, t, ##s)
  50.  
  51. #ifdef MPEG2_MAP
  52. # define DUMP_MAP(t, s...)    WRITE_OUT(t, ##s)
  53. #else
  54. # define DUMP_MAP(t, s...)      /* */
  55. #endif
  56.  
  57. #ifdef MPEG2_DEBUG
  58. # define DUMP_DEBUG(t, s...)    WRITE_OUT(t, ##s)
  59. #else
  60. # define DUMP_DEBUG(t, s...)    /* */
  61. #endif
  62.  
  63. // NOTES
  64.  
  65. // I'm assuming that GOP and picture start codes are not split across
  66. // packet boundries
  67.  
  68. // Any edits must set broken_link to "1" if the prior GOP has been
  69. // dropped?
  70.  
  71.  
  72. MPEG2Parser::MPEG2Parser():Parser()
  73. {
  74.     picture_list = NULL;
  75.     packet_list = NULL;
  76.     video_list = NULL;
  77.     audio_list = NULL;
  78.     GOP_list = NULL;
  79.     ignore_endcode = false;
  80.     first_pack = new FirstPack();   //TI!
  81. }
  82.  
  83. MPEG2Parser::~MPEG2Parser()
  84. {
  85.     if (packet_list)
  86.         delete packet_list;
  87.     if (picture_list)
  88.         delete picture_list;
  89.     if (GOP_list)
  90.         delete GOP_list;
  91.     if (video_list)
  92.         delete video_list;
  93.     if (audio_list)
  94.         delete audio_list;
  95. }
  96.  
  97. void MPEG2Parser::set_ignore_endcode(bool setting)
  98. {
  99.     ignore_endcode = setting;
  100. }
  101.  
  102. List *MPEG2Parser::getGOPs()
  103. {
  104.     return GOP_list;
  105. }
  106.  
  107. List *MPEG2Parser::getPackets()
  108. {
  109.     return packet_list;
  110. }
  111.  
  112. List *MPEG2Parser::getVideo()
  113. {
  114.     return video_list;
  115. }
  116.  
  117. List *MPEG2Parser::getAudio()
  118. {
  119.     return audio_list;
  120. }
  121.  
  122. List *MPEG2Parser::getPictures()
  123. {
  124.     return picture_list;
  125. }
  126.  
  127. uint32_t MPEG2Parser::numGOPs()
  128. {
  129.     return GOP_list ? GOP_list->getNum() : 0;
  130. }
  131.  
  132. #define SKIP_BYTES(b)        location+=(b)
  133. #define SKIP_SIZEOF(v)        SKIP_BYTES(sizeof(v))
  134.  
  135. #define ADDERROR(f, s...)    \
  136. {    \
  137.     addError("%s @ %" OFF_T_FORMAT "(%.2f%%): ",    \
  138.         __FUNCTION__, location,    \
  139.                100.0*(float)((float)location/(float)filesize));    \
  140.     addError(f, ##s);    \
  141. }
  142.  
  143. #define VERIFY_FAILED(s,l)    \
  144. {    \
  145.     ADDERROR(_("header %s (length %d) not found\n"),    # s, (l));    \
  146. }
  147. #define ATTACH_FAILED(s,l)    \
  148. {    \
  149.     ADDERROR(_("%s (length %d) structure attach failed\n"), (s), (l));    \
  150. }
  151. #define    FIXME_FAIL(s)    \
  152. {    \
  153.     ADDERROR(_("stream has %s marker! (Need to finish parsing routine...)\n"),(s));\
  154. }
  155. #define CONSUME_FAILED(s, l)    \
  156. {    \
  157.     ADDERROR(_("expecting %s marker (length %d)\n"),    # s, (l) );    \
  158. }
  159.  
  160. #define CheckMaskValue(byte, mask, value)       (((byte) & (mask))==(value))
  161.  
  162. void MPEG2Parser::parse_PES_packet(void)
  163. {
  164.     PES_packet_header_t *header;
  165.     PES_packet_internals_t *internals_area;
  166.     PES_packet_internals_t internals;
  167.     PES_packet_additional_copy_info_t *additional_copy_info;
  168.     uint8_t *PES_private_data;  // 16 bytes
  169.     uint8_t *STD_data;          // 16 bits
  170.     uint8_t *PTS_data;          // 40 bits
  171.     uint8_t *DTS_data;          // 40 bits
  172.     uint8_t *data;              // ES data
  173.  
  174.  
  175.     // for ES extraction
  176.     int type = ES_TYPE_WEIRD;
  177.     uint8_t id = 0;
  178.  
  179.     unsigned int length;
  180.  
  181.     off_t marked_offset;
  182.     off_t data_loc;
  183.     off_t pes_loc;
  184.  
  185.     pes_loc = location;
  186.     if (!(header = (PES_packet_header_t *)attach(sizeof(*header))))
  187.     {
  188.         ATTACH_FAILED(_("header"), sizeof(*header));
  189.         return;
  190.     }
  191.     // verify start code
  192.     if (!verify(header->start_code, 3, (uint8_t*)packet_start_code_prefix))
  193.     {
  194.         VERIFY_FAILED(packet_start_code_prefix, 3);
  195.         return;
  196.     }
  197.  
  198.     length = (header->PES_packet_length[0] << 8) +
  199.         header->PES_packet_length[1];
  200.  
  201. #ifdef MPEG2_PARSE_TO_STDERR
  202.     fprintf(stderr, _("found PES 0x%02X @ %llu (%d bytes)\n"),
  203.             header->stream_id, pes_loc, length);
  204. #endif
  205.  
  206.     switch (header->stream_id)
  207.     {
  208.         // "simple" length info
  209.         case PES_TYPE_private_stream_2:
  210.         case PES_TYPE_ECM_stream:
  211.         case PES_TYPE_EMM_stream:
  212.         case PES_TYPE_program_stream_directory:
  213.         case PES_TYPE_DSMCC_stream:
  214.         case PES_TYPE_H2221E:
  215.         case PES_TYPE_program_stream_map:
  216.             SKIP_BYTES(length);
  217.             break;
  218.  
  219.             if (!(data = (uint8_t *)attach(length)))
  220.             {
  221.                 ATTACH_FAILED(_("stream data"), length);
  222.                 return;
  223.             }
  224.             /*
  225.                if (verbose)
  226.                Report("%d byte%s of odd stream data",
  227.                length,
  228.                length==1?"":"s");
  229.              */
  230.             break;
  231.  
  232.         case PES_TYPE_padding_stream:
  233.             SKIP_BYTES(length);
  234.             break;
  235.  
  236.             if (!(data = (uint8_t *)attach(length)))
  237.             {
  238.                 ATTACH_FAILED(_("padding data"), length);
  239.                 return;
  240.             }
  241.             /*
  242.                if (verbose)
  243.                Report("%d byte%s of padding",
  244.                length,
  245.                length==1?"":"s");
  246.              */
  247.             break;
  248.  
  249.         default:               // total insano flag freakies
  250.             // Report!
  251.             if ((header->stream_id & PES_TYPE_MASK_audio) == PES_TYPE_audio)
  252.             {
  253.                 id = header->stream_id & ~PES_TYPE_MASK_audio;
  254.                 type = ES_TYPE_AUDIO;
  255.  
  256.                 /*
  257.                    if (verbose)
  258.                    Report("found header for audio stream 0x%02X",id);
  259.                  */
  260.             }
  261.             else if (header->stream_id == PES_TYPE_private_stream_1)
  262.             {
  263.                 // assume private stream 1 is going to be DVD audio
  264.                 id = PES_TYPE_private_stream_1;
  265.                 type = ES_TYPE_AUDIO;
  266.  
  267.                 /*
  268.                    if (verbose)
  269.                    Report("found header for DVD audio stream");
  270.                  */
  271.             }
  272.             else if ((header->stream_id & PES_TYPE_MASK_video) ==
  273.                      PES_TYPE_video)
  274.             {
  275.                 id = header->stream_id & ~PES_TYPE_MASK_video;
  276.                 type = ES_TYPE_VIDEO;
  277.  
  278.                 /*
  279.                    if (verbose)
  280.                    Report("found header for video stream 0x%02X", id);
  281.                  */
  282.             }
  283.             else                // if (type==ES_TYPE_WEIRD)
  284.             {
  285.                 ADDERROR(_("Whoa: got PES id 0x%02X.  Skipping...\n"),
  286.                          header->stream_id);
  287.                 SKIP_BYTES(length);
  288.                 break;
  289.             }
  290.  
  291.         // MPEG-1 allows stuffing bytes here
  292.  
  293.         while (forwardMatch(1, (uint8_t*)stuffing_byte))
  294.             {
  295.                 if (!consume(1, (uint8_t*)stuffing_byte))
  296.                 {
  297.                     CONSUME_FAILED(stuffing_byte, 1);
  298.                     return;
  299.                 }
  300.         length --;
  301.         }
  302.  
  303.             // verify marker bits
  304.  
  305.         if (forwardBitMatch(2,0x1)) {
  306.  
  307.         // MPEG 1 STD buffer
  308.         if (!(STD_data = attach(2)))
  309.         {
  310.             ATTACH_FAILED(_("STD data"), 5);
  311.             return;
  312.         }
  313.         length -= 2;
  314.  
  315.         }
  316.  
  317.         if (forwardBitMatch(4,0x2)) {
  318.  
  319.         // MPEG 1 type 2 PES
  320.         if (!(PTS_data = attach(5)))
  321.         {
  322.             ATTACH_FAILED(_("PTS data"), 5);
  323.             return;
  324.         }
  325.         length -= 5;
  326.  
  327.         } else if (forwardBitMatch(4,0x3)) {
  328.  
  329.         // MPEG 1 type 3 PES
  330.         if (!(PTS_data = attach(5)))
  331.         {
  332.             ATTACH_FAILED(_("PTS data"), 5);
  333.             return;
  334.         }
  335.         if (!(DTS_data = attach(5)))
  336.         {
  337.             ATTACH_FAILED(_("DTS data"), 5);
  338.             return;
  339.         }
  340.         length -= 10;
  341.  
  342.         } else if (forwardBitMatch(8,0x15)) {
  343.  
  344.         // MPEG 1 - no header extensions
  345.         if (! attach(1))
  346.         {
  347.             ATTACH_FAILED(_("MPEG 1 flag byte"), 1);
  348.             return;
  349.         }
  350.         length --;
  351.  
  352.         } else if (forwardBitMatch(2,0x2)) {
  353.  
  354.         // MPEG 2 header
  355.         if (!(internals_area = (PES_packet_internals_t*)attach(sizeof(internals))))
  356.         {
  357.             ATTACH_FAILED(_("flag data"), sizeof(internals));
  358.             return;
  359.         }
  360.         // we need to keep a copy of this in case we flip 
  361.         // across mmap boundries.  tricky!
  362.         memcpy(&internals, internals_area, sizeof(internals));
  363.  
  364.         marked_offset = location;
  365.  
  366.         /*
  367.           if (debug) Report("PES_header_data_length: %d",
  368.           internals.PES_header_data_length);
  369.         */
  370.  
  371.         if (CheckMaskValue(internals.bits[1], 0xC0, 0x80))
  372.         {
  373.             if (!(PTS_data = attach(5)))
  374.             {
  375.             ATTACH_FAILED(_("PTS data"), 5);
  376.             return;
  377.             }
  378.             // FIXME: verify marker bits
  379.             /*
  380.               if (debug) Report("has PTS");
  381.             */
  382.         }
  383.         if (CheckMaskValue(internals.bits[1], 0xC0, 0xC0))
  384.         {
  385.             if (!(PTS_data = attach(5)))
  386.             {
  387.             ATTACH_FAILED(_("PTS data"), 5);
  388.             return;
  389.             }
  390.             // FIXME: verify marker bits
  391.             /*
  392.               if (debug) Report("has PTS");
  393.             */
  394.             if (!(DTS_data = attach(5)))
  395.             {
  396.             ATTACH_FAILED(_("DTS data"), 5);
  397.             return;
  398.             }
  399.             // FIXME: verify marker bits
  400.             /*
  401.               if (debug) Report("has DTS");
  402.             */
  403.         }
  404.         if (CheckMaskValue(internals.bits[1], 0x20, 0x20))
  405.         {
  406.             FIXME_FAIL("ESCR");
  407.             return;
  408.         }
  409.         if (CheckMaskValue(internals.bits[1], 0x10, 0x10))
  410.         {
  411.             FIXME_FAIL("ES rate");
  412.             return;
  413.         }
  414.         if (CheckMaskValue(internals.bits[1], 0x8, 0x8))
  415.         {
  416.             FIXME_FAIL("DSM trick mode");
  417.             return;
  418.         }
  419.         if (CheckMaskValue(internals.bits[1], 0x4, 0x4))
  420.         {
  421.             if (!
  422.             (additional_copy_info =
  423.              (PES_packet_additional_copy_info_t*)attach(sizeof(*additional_copy_info))))
  424.             {
  425.             ATTACH_FAILED(_("additional copy info"),
  426.                       sizeof(*additional_copy_info));
  427.             return;
  428.             }
  429.             // FIXME: verify marker bit
  430.             /*
  431.               if (debug)
  432.               Report("has additional copy info 0x%02X",
  433.               additional_copy_info->data);
  434.             */
  435.         }
  436.         if (CheckMaskValue(internals.bits[1], 0x2, 0x2))
  437.         {
  438.             // isn't this only used in Transport Streams?
  439.             FIXME_FAIL("PES CRC");
  440.             return;
  441.         }
  442.         if (CheckMaskValue(internals.bits[1], 0x1, 0x1))
  443.         {
  444.             PES_packet_extension_t *extension;
  445.  
  446.             if (!(extension = (PES_packet_extension_t*)attach(sizeof(*extension))))
  447.             {
  448.             ATTACH_FAILED(_("extension data"), sizeof(*extension));
  449.             return;
  450.             }
  451.  
  452.             if (PPE_PES_private_data_flag(extension->bits[0]))
  453.             {
  454.             if (!(PES_private_data = attach(16)))
  455.             {
  456.                 ATTACH_FAILED(_("PES private data"), 16);
  457.                 return;
  458.             }
  459.             }
  460.             if (PPE_pack_header_field_flag(extension->bits[0]))
  461.             {
  462.             uint8_t *pack_field_length;
  463.             if (!(pack_field_length = attach(1)))
  464.             {
  465.                 ATTACH_FAILED(_("PES extension pack field length"),
  466.                       1);
  467.                 return;
  468.             }
  469.             if (!attach(*pack_field_length))
  470.             {
  471.                 ATTACH_FAILED(_("PES extension pack field header"),
  472.                       *pack_field_length);
  473.                 return;
  474.  
  475.             }
  476.             }
  477.             if (PPE_program_packet_sequence_counter_flag
  478.             (extension->bits[0]))
  479.             {
  480.             FIXME_FAIL
  481.                 ("PES extension program packet sequence  counter");
  482.             return;
  483.             }
  484.             if (PPE_P_STD_buffer_flag(extension->bits[0]))
  485.             {
  486.             FIXME_FAIL("PES extension P-STD buffer");
  487.                     return;
  488.             }
  489.             if (PPE_PES_extension_flag_2(extension->bits[0]))
  490.             {
  491.             FIXME_FAIL("second PES extension");
  492.             return;
  493.             }
  494.         }
  495.  
  496.         DUMP_DEBUG("ES packet analysis @ %llu\n", pes_loc);
  497.  
  498.         DUMP_DEBUG("\tPES packet length: %d\n", length);
  499.  
  500.         DUMP_DEBUG("\tmarked_offset (flag start?) @ %llu\n",
  501.                marked_offset);
  502.  
  503.         DUMP_DEBUG("\tPES_header_data_length: %d\n",
  504.                internals.PES_header_data_length);
  505.  
  506.         DUMP_DEBUG("\tstart of non-flags @ %llu\n", location);
  507.  
  508.         off_t newloc = (marked_offset + internals.PES_header_data_length);
  509.         if (location != newloc)
  510.         {
  511.             DUMP_DEBUG
  512.             ("\t\twas at %llu, should be at %llu -- adjusting\n",
  513.              location, newloc);
  514.             location = newloc;
  515.         }
  516.  
  517.         // FIXME: no more than 32 of these
  518.         // FIXME: with above adjustment, I'll never seen stuffing bytes
  519.         while (location - marked_offset < internals.PES_header_data_length
  520.                && forwardMatch(1, (uint8_t*)stuffing_byte))
  521.         {
  522.             if (!consume(1, (uint8_t*)stuffing_byte))
  523.             {
  524.             CONSUME_FAILED(stuffing_byte, 1);
  525.             return;
  526.             }
  527.             DUMP_MAP("\t\tstuffing found @ %llu\n", location - 1);
  528.         }
  529.  
  530.         DUMP_DEBUG("\tstart of non-stuffing @ %llu\n", location);
  531.  
  532.         // adjust down for extra headers (where does this 3 come from?)
  533.         length -= (internals.PES_header_data_length + 3);
  534.  
  535.         } else {
  536.         ADDERROR(_("unknown marker bits (%02x)\n"), internals.bits[0]);
  537.         }
  538.  
  539.             data_loc = location;
  540.             if (!(data = (uint8_t*)attach(length)))
  541.             {
  542.                 ATTACH_FAILED(_("ES data"), length);
  543.                 return;
  544.             }
  545.  
  546.             DUMP_DEBUG("\tdata length calculated to be %d\n", length);
  547.  
  548.             DUMP_DEBUG("\tnext location @ %llu\n", location);
  549.  
  550.             if (type != ES_TYPE_WEIRD)
  551.             {
  552.                 ElementStream *es;
  553.                 es = new ElementStream(data_loc, length, type, id);
  554.  
  555.                 if (type == ES_TYPE_VIDEO)
  556.                 {
  557.                     video_list->add(es);
  558.  
  559.                     /*
  560.                      * Really should do GOP processing here
  561.                      */
  562.                 }
  563.                 else
  564.                 {
  565.                     audio_list->add(es);
  566.                 }
  567.             }
  568.  
  569.             break;
  570.     }
  571. }
  572.  
  573. void MPEG2Parser::parse_system_header(void)
  574. {
  575.     system_header_t *header;
  576.     stream_id_t *stream;
  577.  
  578. #ifdef MPEG2_PARSE_TO_STDERR
  579.     fprintf(stderr, "System @ %llu?\n", location);
  580. #endif
  581.  
  582.     if (!(header = (system_header_t *)attach(sizeof(*header))))
  583.     {
  584.         ATTACH_FAILED(_("header"), sizeof(*header));
  585.         return;
  586.     }
  587.  
  588.     // verify start code
  589.     if (!verify(header->start_code, 4, (uint8_t*)system_header_start_code))
  590.     {
  591.         VERIFY_FAILED(system_header_start_code, 4);
  592.         return;
  593.     }
  594.  
  595. #ifdef MPEG2_PARSE_TO_STDERR
  596.     fprintf(stderr, "\tsystem header: 0x%02X\n", header->start_code[3]);
  597. #endif
  598.  
  599.     
  600.     first_pack->setSystemHeader(header);    //TI! save system header info
  601.     
  602.     // FIXME: verify marker bits
  603.         
  604.     // report!
  605.     /*
  606.     if (verbose) Report("found system_header");
  607.     */
  608.     
  609.     uint16_t index = 0;
  610.     
  611.     while (forwardBitMatch(1, 0x1))
  612.     {
  613.         if (!(stream = (stream_id_t *)attach(sizeof(*stream))))
  614.         {
  615.             ATTACH_FAILED(_("stream header"), sizeof(*stream));
  616.             return;
  617.             }
  618.             // verify stream id
  619.         if ((stream->stream_id & 0xF8) < 0xB8)
  620.         {
  621.             ADDERROR(_("invalid stream_id 0x%02X\n"), stream->stream_id);
  622.             return;
  623.         }
  624.         
  625.         first_pack->addStreamId(stream);    //TI! save stream id info
  626.            
  627.         // report!
  628.         /*
  629.         if (verbose) Report("found stream_id 0x%02X",stream->stream_id);
  630.         */
  631.     }   
  632. }
  633.  
  634. void MPEG2Parser::parse_pack_header(void)
  635. {
  636.     int i;
  637.     pack_header_t *header;
  638.     pack_header_MPEG1_t *MPEG1_header;
  639.     int pack_stuffing_length;
  640.  
  641.     pack_start = location;
  642.  
  643.     // verify start code
  644.     if (!consume(4, (uint8_t*)pack_start_code))
  645.     {
  646.         CONSUME_FAILED(pack_start_code, 4);
  647.         return;
  648.     }
  649.  
  650.     // verify marker bits
  651.     if (forwardBitMatch(4,0x2)) {
  652.         // MPEG 1
  653.         if (!(MPEG1_header = (pack_header_MPEG1_t*)attach(sizeof(*MPEG1_header))))
  654.         {
  655.                ATTACH_FAILED(_("MPEG1_header"), sizeof(*MPEG1_header));
  656.                return;
  657.         }
  658.  
  659.         printf("Detected MPEG1 stream!  This is experimental code.\n",
  660.                pack_start);
  661.  
  662. #ifdef MPEG2_PARSE_TO_STDERR
  663.         fprintf(stderr, "found MPEG-1 Pack @ %llu?\n", pack_start);
  664. #endif
  665.     } else if (forwardBitMatch(2,0x1)) {
  666.         // MPEG 2
  667.         if (!(header = (pack_header_t*)attach(sizeof(*header))))
  668.         {
  669.                ATTACH_FAILED(_("header"), sizeof(*header));
  670.                return;
  671.         }
  672.  
  673. #ifdef MPEG2_PARSE_TO_STDERR
  674.         fprintf(stderr, "found MPEG-2 Pack @ %llu?\n", pack_start);
  675. #endif
  676.  
  677.         first_pack->setPackHeader(header);  //TI! save pack header info
  678.  
  679.         pack_stuffing_length = header->bits[9] & 0x7;
  680.  
  681.         // report!
  682.         /*
  683.            if (verbose)
  684.            Report("pack_header found");
  685.          */
  686.  
  687.         for (i = 0; i < pack_stuffing_length; i++)
  688.         {
  689.             if (!consume(1, (uint8_t*)stuffing_byte))
  690.             {
  691.                 CONSUME_FAILED(stuffing_byte, 1);
  692.                 return;
  693.             }
  694.         }
  695.     } 
  696.     else {
  697.         ADDERROR(_("Neither MPEG1 nor MPEG2 Pack header - 0x%02x!\n"),
  698.                 MPEG1_header->bits[0]);
  699.         consume(4, (uint8_t*)pack_start_code);
  700.     }
  701.  
  702.     if (forwardMatch(4, (uint8_t*)system_header_start_code))
  703.         parse_system_header();
  704. }
  705.  
  706.  
  707. void MPEG2Parser::parse_pack(void)
  708. {
  709.     parse_pack_header();
  710.     while (location + sizeof(PES_packet_header_t) <= filesize &&
  711.            forwardMatch(3, (uint8_t*)packet_start_code_prefix) &&
  712.            !forwardMatch(4, (uint8_t*)pack_start_code) &&
  713.            (ignore_endcode || !forwardMatch(4, (uint8_t*)MPEG_program_end_code)))
  714.         parse_PES_packet();
  715. }
  716.  
  717. /*
  718.  * This function steps through the stream, looking for "Pack" boundries.
  719.  * For each pack boundry, all the PES packets within it are examined and
  720.  * added to the overall index of packets.  We track the video and audio
  721.  * packets by simply saying "here where the next _will_ go" (first_video),
  722.  * before we've actually seen it.  Once we're done processing a pack, we
  723.  * store our current video position as the 'max'.
  724.  *
  725.  */
  726. void MPEG2Parser::parse_MPEG2_program_stream(void)
  727. {
  728.     Pack *packet;
  729.  
  730.     int first_video;
  731.     int first_audio;
  732.     int error_found = 0;
  733.  
  734.     char *task = _("Reading MPEG2");
  735.  
  736.     setParsingState(PARSER_STATE_PARSING);
  737.  
  738.     while ((location < filesize)
  739.               && (ignore_endcode ||
  740.                   !forwardMatch(4,(uint8_t*)MPEG_program_end_code)))
  741.     {
  742.         // callback our progress
  743.         if (tick)
  744.             tick(task, (float) ((float) location / (float) filesize));
  745.  
  746.         if (forwardMatch(4, (uint8_t*)pack_start_code))
  747.         {
  748.  
  749.             first_video = video_list->getNum();
  750.             first_audio = audio_list->getNum();
  751.  
  752.             parse_pack();
  753.  
  754.             // did we see a packet?
  755.             if (pack_start != location)
  756.             {
  757.                 packet = new Pack(pack_start, location - pack_start,
  758.                                   first_video, video_list->getNum(),
  759.                                   first_audio, audio_list->getNum(),
  760.                                   error_found);
  761.                 packet_list->add(packet);
  762.                 error_found = 0;
  763.             }
  764.         }
  765.         else
  766.         {
  767.             // abort if we're out of data (any code is at least 6)
  768.             if (location + sizeof(PES_packet_header_t) >= filesize)
  769.                 break;
  770.  
  771.             // if we didn't match a pack_start_code
  772.             // then we should see an MPEG_program_end_code
  773.             // if not, we hit garbage
  774.             if (!forwardMatch(4, (uint8_t*)MPEG_program_end_code))
  775.             {
  776.                 uint8_t *garbage;
  777.                 int garbage_count;
  778.                 off_t garbage_start;
  779.                 char report[REPORT_LENGTH];
  780.  
  781.                 garbage = examine(4);
  782.  
  783.                 ADDERROR(_
  784.                          ("expecting pack_start_code, got 0x%02X 0x%02X 0x%02X 0x%02X\n"),
  785.                          garbage[0], garbage[1], garbage[2], garbage[3]);
  786.  
  787.                 garbage_start = location;
  788.  
  789.                 error_found = 1;
  790.  
  791.                 garbage_count = 0;
  792.                 while (location < filesize &&
  793.                        garbage_count < 102400 &&
  794.                        !forwardMatch(4, (uint8_t*)pack_start_code))
  795.                 {
  796.                     SKIP_SIZEOF(uint8_t);
  797.                     garbage_count++;
  798.                 }
  799.                 snprintf(report,REPORT_LENGTH,
  800.                          _("garbage data seen from %%%s to %%%s.\n"),
  801.                          OFF_T_FORMAT,OFF_T_FORMAT);
  802.                 ADDERROR(report, garbage_start, location);
  803.                 if (garbage_count == 102400)
  804.                 {
  805.                     ADDERROR(_
  806.                              ("More than 100K of garbage -- aborting parse.\n"));
  807.                     break;
  808.                 }
  809.                 else if (location < filesize)
  810.                 {
  811.                     ADDERROR(_("found long-lost pack_start_code\n"));
  812.                 }
  813.             }
  814.         }
  815.     }
  816.     // They *should* have end code, but nothing ever does
  817.     // Therefore, we'll skip this test if we're EOF
  818.     if (location != filesize && !consume(4, (uint8_t*)MPEG_program_end_code))
  819.     {
  820.         CONSUME_FAILED(MPEG_program_end_code, 4);
  821.     }
  822.  
  823.     if (tick)
  824.         tick(task, 1.0);
  825.  
  826.     setParsingState(PARSER_STATE_FINISHED);
  827. }
  828.  
  829. // FIXME: Assumes headers will be fully contained by single video ES packet
  830. Vector *MPEG2Parser::findCode(Vector * area, uint8_t * code, size_t size)
  831. {
  832.     uint8_t *buf;
  833.     uint8_t *head;
  834.     uint8_t *ptr;
  835.     size_t tosearch;
  836.     uint8_t *header = NULL;
  837.  
  838.     tosearch = area->getLen();
  839.  
  840.     // can't search what we don't have
  841.     if (size > tosearch)
  842.         return NULL;
  843.  
  844.     if (!(buf = bytesAvail(area->getStart(), tosearch)))
  845.         return NULL;
  846.     head = buf;
  847.  
  848.     // Can't scan x-1 few bytes for an x-byte marker
  849.     tosearch -= (size - 1);
  850.  
  851.     while (tosearch > 0)
  852.     {
  853.         if ((ptr = (uint8_t*)memchr(buf, 0x00, tosearch)))
  854.         {
  855.             if (verify(ptr, 4, code))
  856.             {
  857.                 header = ptr;
  858.                 break;
  859.             }
  860.             // advance searcher and buffer head
  861.             tosearch -= (ptr - buf) + 1;
  862.             buf = ptr + 1;
  863.         }
  864.         else
  865.             tosearch = 0;
  866.     }
  867.  
  868.  
  869.     if (header)
  870.         return new Vector(area->getStart() + (header - head), size);
  871.  
  872.     return NULL;
  873. }
  874.  
  875. #define GOPADDERROR(f, s...)    \
  876. {    \
  877.     addError("%s @ %" OFF_T_FORMAT "(%.2f%%): ",    \
  878.         __FUNCTION__, header->getStart(),    \
  879.                100.0*(float)((float)header->getStart()/(float)filesize));    \
  880.     addError(f, ##s);    \
  881. }
  882.  
  883. /*
  884.  * This function examines the list of Packs and creates the GOP table.
  885.  * Packs track video and audio packet vectors.
  886.  * GOPs track Packs and Pictures
  887.  * Pictures track video vectors.
  888.  */
  889. void MPEG2Parser::buildGOPs(void)
  890. {
  891.     GroupOfPictures *GOP = NULL;
  892.     Picture *picture = NULL;
  893.  
  894.     int packet_index;
  895.     int packet_max;
  896.  
  897.     char *task = _("Building GOP table");
  898.  
  899.     int GOP_count = 0;
  900.     int picture_count = 0;
  901.  
  902.     int fake_GOPs = 0;
  903.     int I_frame_count = 0;
  904.  
  905.     // verify MPEG2's internals
  906.     if (!packet_list)
  907.     {
  908.         printf("%s", _("NULL packet list?!\n"));
  909.         return;
  910.     }
  911.     if (!video_list)
  912.     {
  913.         printf("%s", _("NULL video list?!\n"));
  914.         return;
  915.     }
  916.     if (!audio_list)
  917.     {
  918.         printf("%s", _("NULL audio list?!\n"));
  919.         return;
  920.     }
  921.     if (!picture_list)
  922.     {
  923.         printf("%s", _("NULL picture list?!\n"));
  924.         return;
  925.     }
  926.     if (!GOP_list)
  927.     {
  928.         printf("%s", _("NULL GOP list?!\n"));
  929.         return;
  930.     }
  931.  
  932.     packet_max = packet_list->getNum();
  933.     for (packet_index = 0; packet_index < packet_max; packet_index++)
  934.     {
  935.         Pack *packet;
  936.         int pack_ves_first, pack_aes_first;
  937.         int pack_ves_index, pack_aes_index;
  938.         int pack_ves_max, pack_aes_max;
  939.  
  940.         // update status bar
  941.         if (tick)
  942.             tick(task, (float) ((float) packet_index / (float) packet_max));
  943.  
  944.         if (!(packet = (Pack *) packet_list->vector(packet_index)))
  945.         {
  946.             printf("%s", _("NULL packet?!\n"));
  947.             return;
  948.         }
  949.  
  950.         if (packet->getFoundError())
  951.         {
  952.             ADDERROR(_("Garbage was detected at GOP %d\n"), GOP_count - 1);
  953.         }
  954.  
  955.  
  956.         DUMP_MAP("Pack: %d @ %llu-%llu\n",
  957.                  packet_index,
  958.                  packet->getStart(),
  959.                  packet->getStart() + packet->getLen() - 1);
  960.  
  961.         pack_ves_first = packet->getVideoFirst();
  962.         pack_ves_max = packet->getVideoMax();
  963.  
  964.         for (pack_ves_index = pack_ves_first;
  965.              pack_ves_index < pack_ves_max; pack_ves_index++)
  966.         {
  967.             ElementStream *ves;
  968.             Vector *header;
  969.  
  970.             if (!(ves = (ElementStream *) video_list->vector(pack_ves_index)))
  971.             {
  972.                 printf("%s", _("NULL VES?!\n"));
  973.                 return;
  974.             }
  975.  
  976.             DUMP_MAP("\tVES: %d @ %llu-%llu\n",
  977.                      pack_ves_index,
  978.                      ves->getStart(), ves->getStart() + ves->getLen() - 1);
  979.  
  980.             // first VES packet in system packet will
  981.             // be checked for GOP... (not really "proper")
  982.             // but is the only sane way to handle GOP editing
  983.             // without a full stream demuxer
  984.             if (pack_ves_index == pack_ves_first) {
  985.                 bool saw_sequence = false;
  986.                 sequence_header seq_header;
  987.                 struct sequence_info info;
  988.  
  989.                 memset(&info,0,sizeof(info));
  990.  
  991.                 // look for sequence header
  992.                 if ((header = findCode(ves, (uint8_t*)sequence_start_code,
  993.                                        sizeof(sequence_header)))) {
  994.                     uint8_t *bytes;
  995.  
  996.                     if (!(bytes = bytesAvail(header->getStart(), sizeof(sequence_header))))
  997.                     {
  998.                         printf("%s", _("Sequence header not available?!\n"));
  999.                     }
  1000.                     else
  1001.                     {
  1002.                         memcpy(&seq_header,bytes,sizeof(sequence_header));
  1003.                         bytes+=4; // skip the header codes
  1004.  
  1005.                         // see mpegcat.c for formula details
  1006.                         info.horizontal_size = (bytes[0] << 4) |
  1007.                                                 ((bytes[1] & 0xF0) >> 4);
  1008.                         info.vertical_size = ((bytes[1] & 0x0F) << 8) |
  1009.                                                 bytes[2];
  1010.                         info.aspect_ratio = (bytes[3] & 0xF0) >> 4;
  1011.                         info.frame_rate = (bytes[3] & 0x0F);
  1012.                         info.bit_rate =
  1013.                             (bytes[4] << 10) | (bytes[5] << 2) |
  1014.                             ((bytes[6] & 0xC0) >> 6);
  1015.                         info.constrained = (bytes[7] & 0x04) >> 2;
  1016.  
  1017.                         saw_sequence = true;
  1018.  
  1019.                         /*
  1020.                         printf("Sequence Header (%dx%d: %s, %sfps, %s%s)\n",
  1021.                             info.horizontal_size, info.vertical_size,
  1022.                             aspect_str[info.aspect_ratio],
  1023.                             frame_str[info.frame_rate],
  1024.                             speed_str(info.bit_rate * 400),
  1025.                             info.constrained ? " constrained" : "");
  1026.                         */
  1027.                     }
  1028.                 }
  1029.  
  1030.                 // look for GOP
  1031.                 if ((header = findCode(ves, (uint8_t*)group_start_code, 8))) {
  1032.                     GOP = new GroupOfPictures(header);
  1033.                     if (saw_sequence) {
  1034.                         GOP->set_sequence_info(&info);
  1035.                         GOP->set_sequence_header(&seq_header);
  1036.                     }
  1037.                     GOP_list->add(GOP);
  1038.  
  1039.                     GOP_count++;
  1040.                     DUMP_MAP("\t\tGOP: %d @ %llu\n", GOP_count,
  1041.                          header->getStart());
  1042.  
  1043.                     // we found a real GOP, so no more fake ones
  1044.                     fake_GOPs = 0;
  1045.                     I_frame_count = 0;
  1046.                 }
  1047.             }
  1048.  
  1049.             if ((header = findCode(ves, (uint8_t*)picture_start_code, 6)))
  1050.             {
  1051.                 uint8_t *area;
  1052.                 int pic_type;
  1053.                 int pic_time;
  1054.  
  1055.                 area = bytesAvail(header->getStart(), header->getLen());
  1056.                 pic_type = (area[5] & PICTURE_CODING_MASK) >> 3;
  1057.                 pic_time = area[4];
  1058.                 pic_time <<= 2;
  1059.                 pic_time |= ((area[5] & 0xC0) >> 6);
  1060.  
  1061.                 picture = new Picture(header->getStart(), header->getLen(),
  1062.                                       pic_type, pic_time);
  1063.                 picture_list->add(picture);
  1064.  
  1065.                 DUMP_MAP("\t\t\tPicture %d (%s) @ %llu\n",
  1066.                          picture_count++,
  1067.                          pic_str[pic_type], header->getStart());
  1068.  
  1069.                 if (pic_type == PICTURE_CODING_INTRA)
  1070.                 {
  1071.                     I_frame_count++;
  1072.  
  1073.                     if (!GOP || (fake_GOPs))
  1074.                     {
  1075.                         GOPADDERROR(_
  1076.                                     ("Whoa: no GOP seen before an I-Frame!?\n (You might want to re-multiplex your MPEG2-PS file first.)\n"));
  1077. #if 0
  1078.                         // in the situation where we don't find a
  1079.                         // GOP, we can play along and try to trick
  1080.                         // ourself into thinking this MPEG2-PS file
  1081.                         // actually has GOP headers.
  1082.  
  1083.                         if (!fake_GOPs)
  1084.                             ADDERROR(_
  1085.                                      ("No GOP seen before first Picture header.  Attempting to do I-frame splitting...\n"));
  1086.                         fake_GOPs = 1;
  1087.  
  1088.                         // FIXME: build a better GOP header???!
  1089.  
  1090.                         GOP = new GroupOfPictures(header);
  1091.                         GOP_list->add(GOP);
  1092.  
  1093.                         GOP_count++;
  1094.                         DUMP_MAP("\t\tPretend GOP: %d @ %llu\n", GOP_count,
  1095.                                  header->getStart());
  1096. #endif
  1097.                     }
  1098.  
  1099.                     if (I_frame_count > 1)
  1100.                     {
  1101.                         GOPADDERROR(_
  1102.                                     ("Whoa: I-Frame number %d seen in the same GOP!?\n (You might want to re-multiplex your MPEG2-PS file first.)\n"),
  1103.                                     I_frame_count);
  1104.  
  1105.                     }
  1106.                 }
  1107.  
  1108.                 if (GOP)
  1109.                     GOP->getPictureBounds()->extendTo(picture_list->getNum());
  1110.             }
  1111.  
  1112.             if (picture)
  1113.                 picture->getVideoBounds()->extendTo(pack_ves_index + 1);
  1114.  
  1115.  
  1116.         }
  1117.  
  1118.         // Don't forget trailing packets...
  1119.         if (picture)
  1120.             picture->getVideoBounds()->extendTo(pack_ves_index);
  1121.  
  1122.         // handle imbedded audio packets too!
  1123.         pack_aes_first = packet->getAudioFirst();
  1124.         pack_aes_max = packet->getAudioMax();
  1125.  
  1126.         for (pack_aes_index = pack_aes_first;
  1127.              pack_aes_index < pack_aes_max; pack_aes_index++)
  1128.         {
  1129.             ElementStream *aes;
  1130.             Vector *header;
  1131.  
  1132.             if (!(aes = (ElementStream *) audio_list->vector(pack_aes_index)))
  1133.             {
  1134.                 printf("%s", _("NULL AES?!\n"));
  1135.                 return;
  1136.             }
  1137.  
  1138.             DUMP_MAP("\tAES: %d @ %llu-%llu\n",
  1139.                      pack_aes_index,
  1140.                      aes->getStart(), aes->getStart() + aes->getLen() - 1);
  1141.  
  1142.         }
  1143.  
  1144.         // we want to INCLUDE this packet, so packet_index+1
  1145.         if (GOP)
  1146.             GOP->getPacketBounds()->extendTo(packet_index + 1);
  1147.  
  1148.     }
  1149.     // Don't forget trailing packets...
  1150.     if (GOP)
  1151.         GOP->getPacketBounds()->extendTo(packet_index);
  1152. }
  1153.  
  1154. int MPEG2Parser::parse(char ignore_errors)
  1155. {
  1156.     clearError();
  1157.     report_errors = !ignore_errors;
  1158.  
  1159.     // reset and clear lists
  1160.     if (GOP_list)
  1161.         GOP_list->reset();
  1162.     else
  1163.     {
  1164.         if (!(GOP_list = new List))
  1165.         {
  1166.             reset();
  1167.             addError("cannot allocate GOP list\n");
  1168.             return FALSE;
  1169.         }
  1170.     }
  1171.     if (packet_list)
  1172.         packet_list->reset();
  1173.     else
  1174.     {
  1175.         if (!(packet_list = new List))
  1176.         {
  1177.             reset();
  1178.             addError("cannot allocate packet list\n");
  1179.             return FALSE;
  1180.         }
  1181.     }
  1182.  
  1183.     if (video_list)
  1184.         video_list->reset();
  1185.     else
  1186.     {
  1187.         if (!(video_list = new List))
  1188.         {
  1189.             reset();
  1190.             addError("cannot allocate video ES list\n");
  1191.             return FALSE;
  1192.         }
  1193.     }
  1194.  
  1195.     if (audio_list)
  1196.         audio_list->reset();
  1197.     else
  1198.     {
  1199.         if (!(audio_list = new List))
  1200.         {
  1201.             reset();
  1202.             addError("cannot allocate audio ES list\n");
  1203.             return FALSE;
  1204.         }
  1205.     }
  1206.  
  1207.     if (picture_list)
  1208.         picture_list->reset();
  1209.     else
  1210.     {
  1211.         if (!(picture_list = new List))
  1212.         {
  1213.             reset();
  1214.             addError("cannot allocate Picture list\n");
  1215.             return FALSE;
  1216.         }
  1217.     }
  1218.  
  1219.     picture_start = 0;
  1220.     GOP_start = 0;
  1221.  
  1222. #ifdef MPEG2_DUMP
  1223.     report = fopen("mpeg2parsing.output", "w");
  1224. #endif
  1225.  
  1226.     parse_MPEG2_program_stream();
  1227.  
  1228.     buildGOPs();
  1229.  
  1230.     //printf(_("GOPs: %d\n"),numGOPs());
  1231.  
  1232. #ifdef MPEG2_DUMP
  1233.     fclose(report);
  1234. #endif
  1235.  
  1236.     if (!GOP_list || !GOP_list->getNum())
  1237.     {
  1238.         //reset();
  1239.         addError("No Groups of Pictures found!\n");
  1240.         return FALSE;
  1241.     }
  1242.  
  1243.     return TRUE;
  1244. }
  1245.  
  1246. /* TI! *
  1247.  * Return first dummy pack
  1248.  */
  1249. FirstPack *MPEG2Parser::getFirstPack(){
  1250.     return first_pack;
  1251. }
  1252.     
  1253.     
  1254.  
  1255. /* vi:set ai ts=4 sw=4 expandtab: */
  1256.