Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

frame.h

Go to the documentation of this file.
00001 /*
00002 * frame.h -- utilities for process digital video frames
00003 * Copyright (C) 2000 Arne Schirmacher <arne@schirmacher.de>
00004 * Copyright (C) 2001-2007 Dan Dennedy <dan@dennedy.org>
00005 *
00006 * This program is free software; you can redistribute it and/or modify
00007 * it under the terms of the GNU General Public License as published by
00008 * the Free Software Foundation; either version 2 of the License, or
00009 * (at your option) any later version.
00010 *
00011 * This program is distributed in the hope that it will be useful,
00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 * GNU General Public License for more details.
00015 *
00016 * You should have received a copy of the GNU General Public License
00017 * along with this program; if not, write to the Free Software Foundation,
00018 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #ifndef _FRAME_H
00022 #define _FRAME_H 1
00023 
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #include <iostream>
00029 using std::cerr;
00030 using std::endl;
00031 
00032 #include <time.h>
00033 #include <string>
00034 #include <stdio.h>
00035 #include <samplerate.h>
00036 
00037 #include "endian_types.h"
00038 #include "playlist.h"
00039 
00040 #ifdef HAVE_LIBDV
00041 #include <libdv/dv.h>
00042 #include <libdv/dv_types.h>
00043 #else
00044 #define DV_AUDIO_MAX_SAMPLES 1944
00045 #endif
00046 
00047 #if defined(HAVE_LIBAVCODEC)
00048 extern "C"
00049 {
00050 #   include <avcodec.h>
00051 #   include <avformat.h>
00052 #ifdef HAVE_SWSCALE
00053 #   include <swscale.h>
00054 #endif
00055 }
00056 #endif
00057 
00058 #define FRAME_MAX_WIDTH 720
00059 #define FRAME_MAX_HEIGHT 576
00060 
00061 typedef struct Pack
00062 {
00064     unsigned char data[ 5 ];
00065 }
00066 Pack;
00067 
00068 typedef struct TimeCode
00069 {
00070     int hour;
00071     int min;
00072     int sec;
00073     int frame;
00074 }
00075 TimeCode;
00076 
00077 
00078 typedef struct AudioInfo
00079 {
00080     int frames;
00081     int frequency;
00082     int samples;
00083     int channels;
00084     int quantization;
00085 }
00086 AudioInfo;
00087 
00088 
00089 class VideoInfo
00090 {
00091 public:
00092     int width;
00093     int height;
00094     bool isPAL;
00095     TimeCode timeCode;
00096     struct tm   recDate;
00097 
00098     VideoInfo();
00099 };
00100 
00101 
00102 class Frame
00103 {
00104 public:
00105     unsigned char *data;
00107     int bytesInFrame;
00108 
00109 #if defined(HAVE_LIBAVCODEC)
00110     AVCodecContext *libavcodec;
00111 #if defined(HAVE_SWSCALE)
00112     struct SwsContext *imgConvertRgbCtx;
00113     struct SwsContext *imgConvertYuvCtx;
00114 #endif
00115 #endif
00116 
00117 #ifdef HAVE_LIBDV
00118     dv_decoder_t *decoder;
00119     dv_encoder_t *encoder;
00120 #endif
00121 
00122     int16_t *audio_buffers[ 4 ];
00123 
00124 public:
00125     Frame();
00126     ~Frame();
00127 
00128     Frame& operator=( const Frame& );
00129     bool GetSSYBPack( int packNum, Pack &pack ) const;
00130     bool GetVAUXPack( int packNum, Pack &pack ) const;
00131     bool GetAAUXPack( int packNum, Pack &pack ) const;
00132     bool GetTimeCode( TimeCode &timeCode ) const;
00133     bool GetRecordingDate( struct tm &recDate ) const;
00134     std::string GetRecordingDate( void ) const;
00135     bool GetAudioInfo( AudioInfo &info ) const;
00136     bool GetVideoInfo( VideoInfo &info ) const;
00137     int GetFrameSize( void ) const;
00138     float GetFrameRate( void ) const;
00139     bool IsPAL( void ) const;
00140     bool IsNewRecording( void ) const;
00141     bool IsNormalSpeed( void ) const;
00142     bool IsComplete( void ) const;
00143     int ExtractAudio( void *sound ) const;
00144 
00145 #ifdef HAVE_LIBDV
00146     void SetPreferredQuality( );
00147     int ExtractAudio( int16_t **channels ) const;
00148     void ExtractHeader( void );
00149     void Deinterlace( uint8_t *pdst, uint8_t *psrc, int stride, int height );
00150     int ExtractRGB( void *rgb );
00151     int ExtractPreviewRGB( void *rgb );
00152     int ExtractYUV( void *yuv );
00153     int ExtractYUV420( uint8_t *yuv, uint8_t *output[ 3 ] );
00154     int ExtractPreviewYUV( void *yuv );
00155     void GetUpperField( void *image, int bpp );
00156     void GetLowerField( void *image, int bpp );
00157     bool IsWide( void ) const;
00158     int GetWidth();
00159     int GetHeight();
00160     bool CreateEncoder( bool isPAL, bool isWide );
00161     void SetRecordingDate( time_t *datetime, int frame );
00162     void SetTimeCode( int frame );
00163     bool EncodeAudio( AudioInfo &info, int16_le_t **channels );
00164 #if BYTE_ORDER == BIG_ENDIAN
00165     bool EncodeAudio( AudioInfo &info, int16_ne_t **channels );
00166 #endif
00167     int CalculateNumberSamples( int frequency, int iteration );
00168     void EncodeRGB( uint8_t *rgb );
00169 #endif
00170 
00171 private:
00173     static bool maps_initialized;
00175     static int palmap_ch1[ 2000 ];
00176     static int palmap_ch2[ 2000 ];
00177     static int palmap_2ch1[ 2000 ];
00178     static int palmap_2ch2[ 2000 ];
00179     static int ntscmap_ch1[ 2000 ];
00180     static int ntscmap_ch2[ 2000 ];
00181     static int ntscmap_2ch1[ 2000 ];
00182     static int ntscmap_2ch2[ 2000 ];
00183     static short compmap[ 4096 ];
00184 };
00185 
00186 typedef enum {
00187     AUDIO_RESAMPLE_SRC_SINC_BEST_QUALITY = 0,
00188     AUDIO_RESAMPLE_SRC_SINC_MEDIUM_QUALITY = 1,
00189     AUDIO_RESAMPLE_SRC_SINC_FASTEST = 2,
00190     AUDIO_RESAMPLE_SRC_ZERO_ORDER_HOLD = 3,
00191     AUDIO_RESAMPLE_SRC_LINEAR = 4,
00192     AUDIO_RESAMPLE_INTERNAL = 5
00193 }
00194 AudioResampleType;
00195 
00196 #define BUFFER_LEN 20480
00197 
00198 template <class input_t, class output_t> class AudioResample
00199 {
00200 protected:
00201     double output_rate;
00202     input_t input[ BUFFER_LEN ];
00203     int m_silentFrameCount;
00204 
00205 public:
00206     AudioResample( double rate ) : output_rate( rate ), m_silentFrameCount(0)
00207     { }
00208     virtual ~AudioResample()
00209     { }
00210     virtual void Resample( input_t *samples, double input_rate, int channels, int samples_this_frame )
00211     { }
00212     void Resample( Frame &frame )
00213     {
00214         //  cerr << "Resample -----------------" << endl;
00215         if ( output_rate != 0 )
00216         {
00217             if ( frame.ExtractAudio( input ) == 0 )
00218             {
00219                 size = frame.CalculateNumberSamples( int(output_rate), m_silentFrameCount++ );
00220                 size *= 2 * sizeof(output_t);
00221                 memset( output, 0, size );
00222                 return;
00223             }
00224 
00225             AudioInfo info;
00226             frame.GetAudioInfo( info );
00227             /*
00228             cerr << "Audio info: "
00229                  << "  dec-..->frequency: "
00230                  << info.frequency
00231                  << "  samples: "
00232                  << info.samples << endl;
00233             */
00234             if ( info.frequency && output_rate != info.frequency )
00235             {
00236                 Resample( input,
00237                       info.frequency,
00238                       info.channels,
00239                       info.samples );
00240             }
00241             else
00242             {
00243                 for (int i=0; i<info.channels*info.samples; i++)
00244                     output[i] = input[i];
00245 
00246                 size = info.channels*info.samples*sizeof(output_t);
00247             }
00248         }
00249         else
00250         {
00251             size = 0;
00252         }
00253         // cerr << "size: " << size << endl;
00254     }
00255     void SetOutputFrequency( double output_rate )
00256     {
00257         this->output_rate = output_rate;
00258     }
00259     int GetOutputFrequency( )
00260     {
00261         return this->output_rate;
00262     }
00263 
00264     output_t output[ BUFFER_LEN ];
00265     int size;
00266 };
00267 
00268 template <class input_t, class output_t> class InternalAudioResample : public AudioResample<input_t, output_t>
00269 {
00270 public:
00271     InternalAudioResample( ) : AudioResample<input_t,output_t>( 0 )
00272     { }
00273     InternalAudioResample( double output_rate ) : AudioResample<input_t,output_t>( output_rate )
00274     { }
00275     virtual ~InternalAudioResample()
00276     { }
00281     void Resample( input_t *input, double input_rate, int channels, int samples )
00282     {
00283         float ratio = ( float ) this->output_rate / ( float ) input_rate;
00284         this->size = ( int ) ( ( float ) samples * ratio );
00285 
00286         int rounding = 1 << 15;
00287         unsigned int xfactor = ( samples << 16 ) / this->size;
00288         unsigned int xmax = xfactor * this->size;
00289         unsigned int i = 0;
00290         unsigned int o = 0;
00291         this->size *= sizeof(output_t) * channels;
00292 
00293         for ( unsigned int xft = 0; xft < xmax; xft += xfactor )
00294         {
00295             i = ( ( xft + rounding ) >> 16 ) * channels;
00296             for (int c=0; c < channels; c++)
00297                 this->output[o+c] = input[i+c];
00298             o += channels;
00299         }
00300 
00301     }
00302 };
00303 
00304 template <class input_t, class output_t> class SrcAudioResample : public AudioResample<input_t, output_t>
00305 {
00306 public:
00307     SrcAudioResample( int converter ) : AudioResample<input_t,output_t>( 0 )
00308     {
00309         SrcAudioResample( converter, 0 );
00310     }
00311     SrcAudioResample( int converter, double output_rate, bool isStreaming ) :
00312         AudioResample<input_t,output_t>( output_rate )
00313     {
00314         int srcError = 0;
00315 
00316         state = src_new( converter, 2, &srcError );
00317         if ( srcError != 0 )
00318         {
00319             cerr << "SRC: " << src_strerror( srcError ) << endl;
00320         }
00321         else
00322         {
00323             data.data_in = input_buffer;
00324             data.data_out = output_buffer;
00325             data.end_of_input = isStreaming ? 0 : 1;
00326         }
00327     }
00328     virtual ~SrcAudioResample()
00329     {
00330         src_delete( state );
00331     }
00332     void Resample( input_t *input, double input_rate, int channels, int samples )
00333     {
00334         for ( int i = 0; i < samples * channels; ++i )
00335             input_buffer[ i ] = ( float ) input[ i ] / 32768.0;
00336 
00337         // Setup resampler
00338         data.input_frames = samples;
00339         data.output_frames = BUFFER_LEN / channels;
00340         data.src_ratio = this->output_rate / input_rate;
00341 
00342         // Resample
00343         int result = src_process ( state, &data );
00344         if ( result != 0 )
00345             cerr << "SRC: " << src_strerror( result ) << endl;
00346         this->size = data.output_frames_gen * channels * sizeof(output_t);
00347 
00348 // cerr << "Resample in samples " << samples << " out rate " << this->output_rate << " in rate " << input_rate << " src_ratio " << data.src_ratio << "out samples " << this->size/4 << endl;
00349 
00350         for ( int i = 0; i < data.output_frames_gen * channels; ++i )
00351         {
00352             float sample = output_buffer[ i ];
00353             if ( sample > 1.0 )
00354                 sample = 1.0;
00355             if ( sample < -1.0 )
00356                 sample = -1.0;
00357             if ( sample >= 0 )
00358                 this->output[ i ] = ( long int )( 32767.0 * sample );
00359             else
00360                 this->output[ i ] = ( long int )( 32768.0 * sample );
00361         }
00362     }
00363 
00364 private:
00365     SRC_STATE *state;
00366     SRC_DATA data;
00367     float input_buffer[ BUFFER_LEN ];
00368     float output_buffer[ BUFFER_LEN ];
00369 };
00370 
00371 template <class input_t, class output_t> class AudioResampleFactory
00372 {
00373 public:
00374     static AudioResample<input_t, output_t> *createAudioResample( AudioResampleType type, 
00375         double output_rate = 0, bool isStreaming = true )
00376     {
00377         switch ( type )
00378         {
00379         case AUDIO_RESAMPLE_SRC_SINC_BEST_QUALITY:
00380             return new SrcAudioResample<input_t, output_t>( SRC_SINC_BEST_QUALITY, output_rate, isStreaming );
00381         case AUDIO_RESAMPLE_SRC_SINC_MEDIUM_QUALITY:
00382             return new SrcAudioResample<input_t, output_t>( SRC_SINC_MEDIUM_QUALITY, output_rate, isStreaming );
00383         case AUDIO_RESAMPLE_SRC_SINC_FASTEST:
00384             return new SrcAudioResample<input_t, output_t>( SRC_SINC_FASTEST, output_rate, isStreaming );
00385         case AUDIO_RESAMPLE_SRC_ZERO_ORDER_HOLD:
00386             return new SrcAudioResample<input_t, output_t>( SRC_ZERO_ORDER_HOLD, output_rate, isStreaming );
00387         case AUDIO_RESAMPLE_SRC_LINEAR:
00388             return new SrcAudioResample<input_t, output_t>( SRC_LINEAR, output_rate, isStreaming );
00389         default:
00390             return new InternalAudioResample<input_t, output_t>( output_rate );
00391         }
00392     }
00393 };
00394 
00395 
00396 class FramePool
00397 {
00398 public:
00399     virtual ~FramePool()
00400     { }
00401     virtual Frame *GetFrame( ) = 0;
00402     virtual void DoneWithFrame( Frame * ) = 0;
00403 };
00404 
00405 extern FramePool *GetFramePool( );
00406 
00407 
00416 template <class input_t, class output_t> class AsyncAudioResample
00417 {
00418 private:
00419     SRC_STATE* m_state;
00420     PlayList* m_playlist;
00421     int m_position;
00422     int m_every;
00423     input_t m_input[BUFFER_LEN];
00424     float m_internalInput[BUFFER_LEN];
00425     float m_internalConformed[BUFFER_LEN];
00426     float m_internalOutput[BUFFER_LEN];
00427     output_t m_output[BUFFER_LEN];
00428     int m_error;
00429     Frame& m_frame;
00430     double m_rate;
00431     SRC_STATE* m_conformer;
00432     SRC_DATA m_srcdata;
00433     AudioInfo m_info;
00434     int m_channels;
00435     int m_end;
00436     int m_silentFrameCount;
00437 
00438 public:
00439     AsyncAudioResample( AudioResampleType type, PlayList *playlist, 
00440             double rate, int begin, int end, int every ) :
00441         m_playlist( playlist ),
00442         m_position( begin ),
00443         m_every( every ),
00444         m_error( 0 ),
00445         m_frame( *GetFramePool()->GetFrame() ),
00446         m_rate( rate ),
00447         m_conformer( 0 ),
00448         m_channels( 2 ),
00449         m_end( end ),
00450         m_silentFrameCount( 0 )
00451     {
00452         int src_type;
00453         switch ( type )
00454         {
00455         case AUDIO_RESAMPLE_SRC_SINC_BEST_QUALITY:
00456             src_type = SRC_SINC_BEST_QUALITY;
00457         case AUDIO_RESAMPLE_SRC_SINC_MEDIUM_QUALITY:
00458             src_type = SRC_SINC_MEDIUM_QUALITY;
00459         case AUDIO_RESAMPLE_SRC_SINC_FASTEST:
00460             src_type = SRC_SINC_FASTEST;
00461         case AUDIO_RESAMPLE_SRC_ZERO_ORDER_HOLD:
00462             src_type = SRC_ZERO_ORDER_HOLD;
00463         case AUDIO_RESAMPLE_SRC_LINEAR:
00464             src_type = SRC_LINEAR;
00465         default:
00466             src_type = SRC_SINC_FASTEST;
00467         }
00468         m_state = src_callback_new( AsyncAudioResample::callback, src_type, m_channels, &m_error, this );
00469         if ( m_error == 0 )
00470         {
00471             m_conformer = src_new( src_type, m_channels, &m_error );
00472             if ( m_error == 0 )
00473             {
00474                 m_srcdata.data_in = m_internalInput;
00475                 m_srcdata.data_out = m_internalConformed;
00476                 m_srcdata.output_frames = BUFFER_LEN / m_channels;
00477             }
00478         }
00479     }
00480 
00481     ~AsyncAudioResample()
00482     {
00483         GetFramePool()->DoneWithFrame( &m_frame );
00484         if ( m_state )
00485             src_delete( m_state );
00486         if ( m_conformer )
00487             src_delete( m_conformer );
00488     }
00489 
00490     bool IsError() const
00491     {
00492         return m_error || (m_state && src_error( m_state )) || (m_conformer && src_error( m_conformer ));
00493     }
00494 
00495     std::string GetError() const
00496     {
00497         if ( src_error( m_state ) )
00498             return src_strerror( src_error( m_state ) );
00499         else if ( src_error( m_conformer ) )
00500             return src_strerror( src_error( m_conformer ) );
00501         else
00502             return src_strerror( m_error );
00503     }
00504 
00505     long ReadAudio( float **data )
00506     {
00507 // cerr << "AsyncAudioResample::ReadAudio" << endl;
00508         long output_frames = 0;
00509         if ( m_position <= m_end )
00510         {
00511             if ( m_playlist->GetFrame( m_position, m_frame ) )
00512             {
00513                 int n = m_frame.ExtractAudio( m_input ) / m_channels / sizeof(input_t);
00514 // cerr << "AsyncAudioResample::ReadAudio position " << m_position << " input samples " << n << endl;
00515                 *data = m_internalConformed;
00516                 if ( n == 0 )
00517                 {
00518                     output_frames = m_frame.CalculateNumberSamples( int(m_rate), m_silentFrameCount++ );
00519                     memset( m_internalConformed, 0, sizeof( m_internalConformed ) );
00520                 }
00521                 else
00522                 {
00523                     m_frame.GetAudioInfo( m_info );
00524                     if ( m_rate != m_info.frequency )
00525                     {
00526                         for ( int i = 0; i < n * m_channels; ++i )
00527                             m_internalInput[ i ] = ( float ) m_input[ i ] / 32768.0;
00528                         m_srcdata.input_frames = n;
00529                         m_srcdata.src_ratio = m_rate / m_info.frequency;
00530                         m_srcdata.end_of_input = (m_position > m_end );
00531                         src_process( m_conformer, &m_srcdata );
00532                         output_frames = m_srcdata.output_frames_gen;
00533                     }
00534                     else
00535                     {
00536                         for ( int i = 0; i < n * m_channels; ++i )
00537                             m_internalConformed[ i ] = ( float ) m_input[ i ] / 32768.0;
00538                         output_frames = n;
00539                     }
00540                 }
00541             }
00542             m_position += m_every;
00543         }
00544 
00545         return output_frames;
00546     }
00547 
00548     static long callback(void *cb_data, float **data)
00549     {
00550         AsyncAudioResample<input_t,output_t>* p = static_cast< AsyncAudioResample<input_t,output_t>* >( cb_data );
00551         return p->ReadAudio( data );
00552     }
00553 
00554     int Process( double rate, int samples )
00555     {
00556         int out_samples = src_callback_read( m_state, rate / m_rate, samples, m_internalOutput );
00557 // cerr << "AsyncAudioResample::Process rate " << rate << " req samples " << samples << " out samples " << out_samples << endl;
00558         for ( int i = 0; i < out_samples * m_channels; ++i )
00559         {
00560             float sample = m_internalOutput[ i ];
00561             if ( sample > 1.0 )
00562                 sample = 1.0;
00563             if ( sample < -1.0 )
00564                 sample = -1.0;
00565             if ( sample >= 0 )
00566                 m_output[ i ] = ( long int )( 32767.0 * sample );
00567             else
00568                 m_output[ i ] = ( long int )( 32768.0 * sample );
00569         }
00570         return out_samples;
00571     }
00572 
00573     output_t* GetOutput( void )
00574     {
00575         return m_output;
00576     }
00577 };
00578 
00579 #endif

Generated on Sun Mar 11 22:11:45 2007 for Kino by  doxygen 1.4.2