pes.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:11k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * pes.c: PES packetizer used by the MPEG multiplexers
  3.  *****************************************************************************
  4.  * Copyright (C) 2001, 2002 VideoLAN
  5.  * $Id: pes.c 9130 2004-11-03 18:32:30Z gbazin $
  6.  *
  7.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  8.  *          Eric Petit <titer@videolan.org>
  9.  *
  10.  * This program 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 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program 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 this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #include <stdlib.h>
  28. #include <sys/types.h>
  29. #include <sys/stat.h>
  30. #include <string.h>
  31. #include <errno.h>
  32. #include <fcntl.h>
  33. #include <vlc/vlc.h>
  34. #include <vlc/input.h>
  35. #include <vlc/sout.h>
  36. #ifdef HAVE_UNISTD_H
  37. #   include <unistd.h>
  38. #endif
  39. #include "codecs.h"
  40. #include "pes.h"
  41. #include "bits.h"
  42. #define PES_PAYLOAD_SIZE_MAX 65500
  43. static inline int PESHeader( uint8_t *p_hdr, mtime_t i_pts, mtime_t i_dts,
  44.                              int i_es_size, es_format_t *p_fmt,
  45.                              int i_stream_id, int i_private_id,
  46.                              vlc_bool_t b_mpeg2, vlc_bool_t b_data_alignment,
  47.                              int i_header_size )
  48. {
  49.     bits_buffer_t bits;
  50.     int     i_extra = 0;
  51.     /* For PES_PRIVATE_STREAM_1 there is an extra header after the
  52.        pes header */
  53.     /* i_private_id != -1 because TS use 0xbd without private_id */
  54.     if( i_stream_id == PES_PRIVATE_STREAM_1 && i_private_id != -1 )
  55.     {
  56.         i_extra = 1;
  57.         if( ( i_private_id & 0xf0 ) == 0x80 )
  58.         {
  59.             i_extra += 3;
  60.         }
  61.     }
  62.     bits_initwrite( &bits, 50, p_hdr );
  63.     /* add start code */
  64.     bits_write( &bits, 24, 0x01 );
  65.     bits_write( &bits, 8, i_stream_id );
  66.     switch( i_stream_id )
  67.     {
  68.         case PES_PROGRAM_STREAM_MAP:
  69.         case PES_PADDING:
  70.         case PES_PRIVATE_STREAM_2:
  71.         case PES_ECM:
  72.         case PES_EMM:
  73.         case PES_PROGRAM_STREAM_DIRECTORY:
  74.         case PES_DSMCC_STREAM:
  75.         case PES_ITU_T_H222_1_TYPE_E_STREAM:
  76.             /* add pes data size  */
  77.             bits_write( &bits, 16, i_es_size );
  78.             bits_align( &bits );
  79.             return( bits.i_data );
  80.         default:
  81.             /* arg, a little more difficult */
  82.             if( b_mpeg2 )
  83.             {
  84.                 int i_pts_dts;
  85.                 if( i_pts > 0 && i_dts > 0 &&
  86.                     ( i_pts != i_dts || ( p_fmt->i_cat == VIDEO_ES &&
  87.                       p_fmt->i_codec != VLC_FOURCC('m','p','g','v') ) ) )
  88.                 {
  89.                     i_pts_dts = 0x03;
  90.                     if ( !i_header_size ) i_header_size = 0xa;
  91.                 }
  92.                 else if( i_pts > 0 )
  93.                 {
  94.                     i_pts_dts = 0x02;
  95.                     if ( !i_header_size ) i_header_size = 0x5;
  96.                 }
  97.                 else
  98.                 {
  99.                     i_pts_dts = 0x00;
  100.                     if ( !i_header_size ) i_header_size = 0x0;
  101.                 }
  102.                 bits_write( &bits, 16, i_es_size + i_extra + 3
  103.                              + i_header_size ); // size
  104.                 bits_write( &bits, 2, 0x02 ); // mpeg2 id
  105.                 bits_write( &bits, 2, 0x00 ); // pes scrambling control
  106.                 bits_write( &bits, 1, 0x00 ); // pes priority
  107.                 bits_write( &bits, 1, b_data_alignment ); // data alignement indicator
  108.                 bits_write( &bits, 1, 0x00 ); // copyright
  109.                 bits_write( &bits, 1, 0x00 ); // original or copy
  110.                 bits_write( &bits, 2, i_pts_dts ); // pts_dts flags
  111.                 bits_write( &bits, 1, 0x00 ); // escr flags
  112.                 bits_write( &bits, 1, 0x00 ); // es rate flag
  113.                 bits_write( &bits, 1, 0x00 ); // dsm trick mode flag
  114.                 bits_write( &bits, 1, 0x00 ); // additional copy info flag
  115.                 bits_write( &bits, 1, 0x00 ); // pes crc flag
  116.                 bits_write( &bits, 1, 0x00 ); // pes extention flags
  117.                 bits_write( &bits, 8, i_header_size ); // header size -> pts and dts
  118.                 /* write pts */
  119.                 if( i_pts_dts & 0x02 )
  120.                 {
  121.                     bits_write( &bits, 4, i_pts_dts ); // '0010' or '0011'
  122.                     bits_write( &bits, 3, i_pts >> 30 );
  123.                     bits_write( &bits, 1, 0x01 ); // marker
  124.                     bits_write( &bits, 15, i_pts >> 15 );
  125.                     bits_write( &bits, 1, 0x01 ); // marker
  126.                     bits_write( &bits, 15, i_pts );
  127.                     bits_write( &bits, 1, 0x01 ); // marker
  128.                     i_header_size -= 0x5;
  129.                 }
  130.                 /* write i_dts */
  131.                 if( i_pts_dts & 0x01 )
  132.                 {
  133.                     bits_write( &bits, 4, 0x01 ); // '0001'
  134.                     bits_write( &bits, 3, i_dts >> 30 );
  135.                     bits_write( &bits, 1, 0x01 ); // marker
  136.                     bits_write( &bits, 15, i_dts >> 15 );
  137.                     bits_write( &bits, 1, 0x01 ); // marker
  138.                     bits_write( &bits, 15, i_dts );
  139.                     bits_write( &bits, 1, 0x01 ); // marker
  140.                     i_header_size -= 0x5;
  141.                 }
  142.                 while ( i_header_size )
  143.                 {
  144.                     bits_write( &bits, 8, 0xff );
  145.                     i_header_size--;
  146.                 }
  147.             }
  148.             else /* MPEG1 */
  149.             {
  150.                 int i_pts_dts;
  151.                 if( i_pts > 0 && i_dts > 0 &&
  152.                     ( i_pts != i_dts || p_fmt->i_cat == VIDEO_ES ) )
  153.                 {
  154.                     bits_write( &bits, 16, i_es_size + i_extra + 10 /* + stuffing */ );
  155.                     i_pts_dts = 0x03;
  156.                 }
  157.                 else if( i_pts > 0 )
  158.                 {
  159.                     bits_write( &bits, 16, i_es_size + i_extra + 5 /* + stuffing */ );
  160.                     i_pts_dts = 0x02;
  161.                 }
  162.                 else
  163.                 {
  164.                     bits_write( &bits, 16, i_es_size + i_extra + 1 /* + stuffing */);
  165.                     i_pts_dts = 0x00;
  166.                 }
  167.                 /* FIXME: Now should be stuffing */
  168.                 /* No STD_buffer_scale and STD_buffer_size */
  169.                 /* write pts */
  170.                 if( i_pts_dts & 0x02 )
  171.                 {
  172.                     bits_write( &bits, 4, i_pts_dts ); // '0010' or '0011'
  173.                     bits_write( &bits, 3, i_pts >> 30 );
  174.                     bits_write( &bits, 1, 0x01 ); // marker
  175.                     bits_write( &bits, 15, i_pts >> 15 );
  176.                     bits_write( &bits, 1, 0x01 ); // marker
  177.                     bits_write( &bits, 15, i_pts );
  178.                     bits_write( &bits, 1, 0x01 ); // marker
  179.                 }
  180.                 /* write i_dts */
  181.                 if( i_pts_dts & 0x01 )
  182.                 {
  183.                     bits_write( &bits, 4, 0x01 ); // '0001'
  184.                     bits_write( &bits, 3, i_dts >> 30 );
  185.                     bits_write( &bits, 1, 0x01 ); // marker
  186.                     bits_write( &bits, 15, i_dts >> 15 );
  187.                     bits_write( &bits, 1, 0x01 ); // marker
  188.                     bits_write( &bits, 15, i_dts );
  189.                     bits_write( &bits, 1, 0x01 ); // marker
  190.                 }
  191.                 if( !i_pts_dts )
  192.                 {
  193.                     bits_write( &bits, 8, 0x0F );
  194.                 }
  195.             }
  196.             /* now should be stuffing */
  197.             /* and then pes data */
  198.             bits_align( &bits );
  199.             if( i_stream_id == PES_PRIVATE_STREAM_1 && i_private_id != -1 )
  200.             {
  201.                 bits_write( &bits, 8, i_private_id );
  202.                 if( ( i_private_id&0xf0 ) == 0x80 )
  203.                 {
  204.                     bits_write( &bits, 24, 0 ); // ac3
  205.                 }
  206.             }
  207.             bits_align( &bits );
  208.             return( bits.i_data );
  209.     }
  210. }
  211. int E_( EStoPES )( sout_instance_t *p_sout, block_t **pp_pes, block_t *p_es,
  212.                    es_format_t *p_fmt, int i_stream_id,
  213.                    int b_mpeg2, int b_data_alignment, int i_header_size )
  214. {
  215.     block_t *p_pes;
  216.     mtime_t i_pts, i_dts, i_length;
  217.     uint8_t *p_data;
  218.     int     i_size;
  219.     int     i_private_id = -1;
  220.     uint8_t header[50];     // PES header + extra < 50 (more like 17)
  221.     int     i_pes_payload;
  222.     int     i_pes_header;
  223.     int     i_pes_count = 1;
  224.     /* HACK for private stream 1 in ps */
  225.     if( ( i_stream_id >> 8 ) == PES_PRIVATE_STREAM_1 )
  226.     {
  227.         i_private_id = i_stream_id & 0xff;
  228.         i_stream_id  = PES_PRIVATE_STREAM_1;
  229.     }
  230.     i_pts = p_es->i_pts <= 0 ? 0 : p_es->i_pts * 9 / 100; // 90000 units clock
  231.     i_dts = p_es->i_dts <= 0 ? 0 : p_es->i_dts * 9 / 100; // 90000 units clock
  232.     i_size = p_es->i_buffer;
  233.     p_data = p_es->p_buffer;
  234.     *pp_pes = p_pes = NULL;
  235.     do
  236.     {
  237.         i_pes_payload = __MIN( i_size, PES_PAYLOAD_SIZE_MAX );
  238.         i_pes_header  = PESHeader( header, i_pts, i_dts, i_pes_payload,
  239.                                    p_fmt, i_stream_id, i_private_id, b_mpeg2,
  240.                                    b_data_alignment, i_header_size );
  241.         i_dts = 0; // only first PES has a dts/pts
  242.         i_pts = 0;
  243.         if( p_es )
  244.         {
  245.             p_es = block_Realloc( p_es, i_pes_header, p_es->i_buffer );
  246.             /* reuse p_es for first frame */
  247.             *pp_pes = p_pes = p_es;
  248.             /* don't touch i_dts, i_pts, i_length as are already set :) */
  249.             p_es = NULL;
  250.         }
  251.         else
  252.         {
  253.             p_pes->p_next = block_New( p_sout, i_pes_header + i_pes_payload );
  254.             p_pes = p_pes->p_next;
  255.             p_pes->i_dts    = 0;
  256.             p_pes->i_pts    = 0;
  257.             p_pes->i_length = 0;
  258.             if( i_pes_payload > 0 )
  259.             {
  260.                 p_sout->p_vlc->pf_memcpy( p_pes->p_buffer + i_pes_header,
  261.                                           p_data, i_pes_payload );
  262.             }
  263.             i_pes_count++;
  264.         }
  265.         /* copy header */
  266.         memcpy( p_pes->p_buffer, header, i_pes_header );
  267.         i_size -= i_pes_payload;
  268.         p_data += i_pes_payload;
  269.         p_pes->i_buffer =  i_pes_header + i_pes_payload;
  270.     } while( i_size > 0 );
  271.     /* Now redate all pes */
  272.     i_dts    = (*pp_pes)->i_dts;
  273.     i_length = (*pp_pes)->i_length / i_pes_count;
  274.     for( p_pes = *pp_pes; p_pes != NULL; p_pes = p_pes->p_next )
  275.     {
  276.         p_pes->i_dts = i_dts;
  277.         p_pes->i_length = i_length;
  278.         i_dts += i_length;
  279.     }
  280.     return 0;
  281. }