Update of /cvsroot/audacity/audacity-src/src/import
In directory sc8-pr-cvs11.sourceforge.net:/tmp/cvs-serv20429/src/import

Modified Files:
        ImportFFmpeg.cpp 
Log Message:
Code comments and cosmetic fixes
Slight changes in stream separation code.

Index: ImportFFmpeg.cpp
===================================================================
RCS file: /cvsroot/audacity/audacity-src/src/import/ImportFFmpeg.cpp,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- ImportFFmpeg.cpp    5 Aug 2008 16:39:31 -0000       1.18
+++ ImportFFmpeg.cpp    9 Aug 2008 03:07:17 -0000       1.19
@@ -158,7 +158,7 @@
 typedef struct _streamContext
 {
    bool                 m_use;                           // TRUE = this stream 
will be loaded into Audacity
-   AVStream            *m_stream;                               // an AVStream 
* in gDecFormatCtx->streams[]
+   AVStream            *m_stream;                               // an AVStream 
*
    AVCodecContext      *m_codecCtx;                                   // 
pointer to m_stream->codec
 
    AVPacket             m_pkt;                                        // the 
last AVPacket we read for this stream
@@ -176,6 +176,8 @@
    int                  m_initialchannels;               // number of channels 
allocated when we begin the importing. Assumes that number of channels doesn't 
change on the fly.
 } streamContext;
 
+/// A representative of FFmpeg loader in
+/// the Audacity import plugin list
 class FFmpegImportPlugin : public ImportPlugin
 {
 public:
@@ -188,9 +190,12 @@
    ~FFmpegImportPlugin() { }
 
    wxString GetPluginFormatDescription();
+
+   ///! Probes the file and opens it if appropriate
    ImportFileHandle *Open(wxString Filename);
 };
 
+///! Does acual import, returned by FFmpegImportPlugin::Open
 class FFmpegImportFileHandle : public ImportFileHandle
 {
 
@@ -198,29 +203,59 @@
    FFmpegImportFileHandle(const wxString & name);
    ~FFmpegImportFileHandle();
 
+   ///! Format initialization
+   ///\return true if successful, false otherwise
    bool Init();
+   ///! Codec initialization
+   ///\return true if successful, false otherwise
    bool InitCodecs();
 
 
    wxString GetFileDescription();
    int GetFileUncompressedBytes();
+
+   ///! Imports audio
+   ///\return import status (see Import.cpp)
    int Import(TrackFactory *trackFactory, Track ***outTracks,
       int *outNumTracks, Tags *tags);
 
+   ///! Reads next audio frame
+   ///\return pointer to the stream context structure to which the frame 
belongs to or NULL on error, or 1 if stream is not to be imported.
    streamContext* ReadNextFrame();
+   
+   ///! Decodes the frame
+   ///\param sc - stream context (from ReadNextFrame)
+   ///\param flushing - true if flushing (no more frames left), false otherwise
+   ///\return 0 on success, -1 if it can't decode any further
    int DecodeFrame(streamContext *sc, bool flushing);
+   
+   ///! Writes decoded data into WaveTracks. Called by DecodeFrame
+   ///\param sc - stream context
+   ///\return 0 on success, 1 on error or interruption
    int WriteData(streamContext *sc);
+   
+   ///! Writes extracted metadata to tags object
+   ///\param avf - file context
+   ///\ tags - Audacity tags object
    void WriteMetadata(AVFormatContext *avf, Tags *tags);
+   
+   ///! Called by Import.cpp
+   ///\return number of readable streams in the file
    wxInt32 GetStreamCount()
    {
       return mNumStreams;
    }
-
+   
+   ///! Called by Import.cpp
+   ///\return array of strings - descriptions of the streams
    wxArrayString *GetStreamInfo()
    {
       return mStreamInfo;
    }
 
+   ///! Called by Import.cpp
+   ///\param StreamID - index of the stream in mStreamInfo and mScs arrays
+   ///\param Use - true if this stream should be imported, false otherwise
    void SetStreamUsage(wxInt32 StreamID, bool Use)
    {
       if (StreamID < mNumStreams)
@@ -229,17 +264,17 @@
 
 private:
 
-   AVFormatContext      *mFormatContext;
-   int                   mNumStreams; // mNumstreams is less or equal to 
mFormatContext->nb_streams
-   streamContext       **mScs;
-   wxArrayString        *mStreamInfo;
+   AVFormatContext      *mFormatContext; //!< Format description, also 
contains metadata and some useful info
+   int                   mNumStreams;    //!< mNumstreams is less or equal to 
mFormatContext->nb_streams
+   streamContext       **mScs;           //!< Array of pointers to stream 
contexts. Length is mNumStreams.
+   wxArrayString        *mStreamInfo;    //!< Array of stream descriptions. 
Length is mNumStreams
 
-   bool                  mCancelled;
+   bool                  mCancelled;     //!< True if importing was canceled 
by user
    wxString              mName;
    void                 *mUserData;
-   uint64_t              mNumSamples;
-   uint64_t              mSamplesDone;
-   WaveTrack           ***mChannels;
+   uint64_t              mNumSamples;    //!< Used for progress dialog. May 
not really be a number of samples.
+   uint64_t              mSamplesDone;   //!< Used for progress dialog. May 
not really be a number of samples.
+   WaveTrack           ***mChannels;     //!< 2-dimentional array of 
WaveTrack's. First dimention - streams, second - channels of a stream. Length 
is mNumStreams
 };
 
 
@@ -316,11 +351,15 @@
 
 bool FFmpegImportFileHandle::InitCodecs()
 {
+   // Allocate the array of pointers to hold stream contexts pointers
+   // Some of the allocated space may be unused (corresponds to video, 
subtitle, or undecodeable audio streams)
    mScs = 
(streamContext**)malloc(sizeof(streamContext**)*mFormatContext->nb_streams);
+   // Fill the stream contexts
    for (unsigned int i = 0; i < mFormatContext->nb_streams; i++)
    {
       if (mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO)
       {
+         //Create a context
          streamContext *sc = new streamContext;
          memset(sc,0,sizeof(*sc));
 
@@ -351,6 +390,7 @@
             continue;
          }
 
+         // Stream is decodeable and it is audio. Add it and it's decription 
to the arrays
          wxString strinfo;
          strinfo.Printf(_("Index[%02x] Codec[%S], Language[%S], 
Duration[%d]"),sc->m_stream->id,codec->name,sc->m_stream->language,sc->m_stream->duration);
          mStreamInfo->Add(strinfo);
@@ -358,6 +398,7 @@
       }
       //for video and unknown streams do nothing
    }
+   //It doesn't really returns false, but GetStreamCount() will return 0 if 
file is composed entierly of unreadable streams
    return true;
 }
 
@@ -382,6 +423,7 @@
 
    CreateProgress();
 
+   // Remove stream contexts which are not marked for importing and adjust 
mScs and mNumStreams accordingly
    for (int i = 0; i < mNumStreams;)
    {
       if (!mScs[i]->m_use)
@@ -401,7 +443,10 @@
 
    for (int s = 0; s < mNumStreams; s++)
    {
+      // As you can see, it's really a number of frames.
+      // TODO: use something other than nb_frames for progress reporting 
(nb_frames is not available for some formats). Maybe something from the format 
context?
       mNumSamples += mScs[s]->m_stream->nb_frames;
+      // There is a possibility that number of channels will change over time, 
but we do not have WaveTracks for new channels. Remember the number of channels 
and stick to it.
       mScs[s]->m_initialchannels = mScs[s]->m_stream->codec->channels;
       mChannels[s] = new WaveTrack *[mScs[s]->m_stream->codec->channels];
       int c;
@@ -430,51 +475,50 @@
       }
    }
 
-   int64_t delay = 0;
-   if (mFormatContext->start_time != AV_NOPTS_VALUE)
-   {
-      delay = mFormatContext->start_time;
-      wxLogMessage(wxT("Container start_time = %d, that would be %d 
milliseconds."),mFormatContext->start_time,double(mFormatContext->start_time)/AV_TIME_BASE*1000);
-      //wxLogMessage(wxT("start_time support is not implemented in FFmpeg 
import plugin. Patches are welcome."));
-   }
-
+   // Handles the start_time by creating silence. This may or may not be 
correct.
+   // There is a possibility that we should ignore first N milliseconds of 
audio instead. I do not know.
+   // TODO: Nag FFmpeg devs about start_time until they finally say WHAT is 
this and HOW to handle it.
    for (int s = 0; s < mNumStreams; s++)
    {
       int64_t stream_delay = 0;
       if (mScs[s]->m_stream->start_time != AV_NOPTS_VALUE)
       {
          stream_delay = mScs[s]->m_stream->start_time;
-         wxLogMessage(wxT("Stream %d start_time = %d, that would be %f 
milliseconds."), s, mScs[s]->m_stream->start_time, 
double(mScs[s]->m_stream->start_time)/AV_TIME_BASE*1000);         
+         wxLogMessage(wxT("Stream %d start_time = %d, that would be %f 
milliseconds."), s, mScs[s]->m_stream->start_time, 
double(mScs[s]->m_stream->start_time)/AV_TIME_BASE*1000);
       }
-      if (delay != 0 || stream_delay != 0)
+      if (stream_delay != 0)
       {
          for (int c = 0; c < mScs[s]->m_stream->codec->channels; c++)
          {
             WaveTrack *t = mChannels[s][c];
-            double len = double(delay+stream_delay)/AV_TIME_BASE;
-            t->InsertSilence(0,double(delay+stream_delay)/AV_TIME_BASE);
+            double len = double(stream_delay)/AV_TIME_BASE;
+            t->InsertSilence(0,double(stream_delay)/AV_TIME_BASE);
          }
       }
    }
 
-
+   // This is the heart of the importing process
    streamContext *sc = NULL;
+   // The result of Import() to be returend. It will be something other than 
zero if user canceled or some error appears.
    int res = 0;
+   // Read next frame.
    while ((sc = ReadNextFrame()) != NULL && (res == 0))
    {
+      // ReadNextFrame returns 1 if stream is not to be imported
       if (sc != (streamContext*)1)
       {
+         // Decode frame until it is not possible to decode any further
          while (sc->m_pktRemainingSiz > 0 && (res == 0))
          {
             if (DecodeFrame(sc,false) < 0)
                break;
 
-
+            // If something useable was decoded - write it to mChannels
             if (sc->m_frameValid)
                res = WriteData(sc);
-
          }
 
+         // Cleanup after frame decoding
          if (sc->m_pktValid)
          {
             av_free_packet(&sc->m_pkt);
@@ -488,7 +532,7 @@
    {
       for (int i = 0; i < mNumStreams; i++)
       {
-         if (DecodeFrame(mScs[i], 1) == 0)
+         if (DecodeFrame(mScs[i], true) == 0)
          {
             WriteData(mScs[i]);
 
@@ -501,6 +545,7 @@
       }
    }
 
+   // Something bad happened - destroy everything!
    if (res)
    {
       for (int s = 0; s < mNumStreams; s++)
@@ -521,8 +566,10 @@
       *outNumTracks += mScs[s]->m_stream->codec->channels;
    }
 
+   // Create new tracks
    *outTracks = new Track *[*outNumTracks];
 
+   // Copy audio from mChannels to newly created tracks (destroying mChannels 
elements in process)
    int trackindex = 0;
    for (int s = 0; s < mNumStreams; s++)
    {
@@ -535,7 +582,7 @@
    }
    delete[] mChannels;
 
-
+   // Save metadata
    WriteMetadata(mFormatContext,tags);
 
    return eImportSuccess;
@@ -551,20 +598,22 @@
       return NULL;
    }
 
+   // Find a stream to which this frame belongs to
    for (int i = 0; i < mNumStreams; i++)
    {
       if (mScs[i]->m_stream->index == pkt.stream_index)
          sc = mScs[i];
    }
 
-   //Off-stream packet. Don't panic, just skip it.
-   //When not all streams are selected for import this will happen very often.
+   // Off-stream packet. Don't panic, just skip it.
+   // When not all streams are selected for import this will happen very often.
    if (sc == NULL)
    {
       av_free_packet(&pkt);
       return (streamContext*)1;
    }
 
+   // Copy the frame to the stream context
    memcpy(&sc->m_pkt, &pkt, sizeof(AVPacket));
 
    sc->m_pktValid = 1;
@@ -603,7 +652,7 @@
       // av_fast_realloc() will only reallocate the buffer if 
m_decodedAudioSamplesSiz is 
       // smaller than third parameter. It also returns new size in 
m_decodedAudioSamplesSiz
       //\warning { for some reason using the following macro call right in the 
function call
-      //causes Audacity to crash in some unknown place. With "newsize" it 
works fine }
+      // causes Audacity to crash in some unknown place. With "newsize" it 
works fine }
       int newsize = FFMAX(sc->m_pkt.size*sizeof(*sc->m_decodedAudioSamples), 
AVCODEC_MAX_AUDIO_FRAME_SIZE);
       sc->m_decodedAudioSamples = 
(int16_t*)FFmpegLibsInst->av_fast_realloc(sc->m_decodedAudioSamples, 
          &sc->m_decodedAudioSamplesSiz,
@@ -621,9 +670,9 @@
    // also returns the number of bytes it decoded in the same parameter.
    sc->m_decodedAudioSamplesValidSiz = sc->m_decodedAudioSamplesSiz;
    nBytesDecoded = FFmpegLibsInst->avcodec_decode_audio2(sc->m_codecCtx, 
-      sc->m_decodedAudioSamples,               // out
+      sc->m_decodedAudioSamples,                     // out
       &sc->m_decodedAudioSamplesValidSiz,      // in/out
-      pDecode, nDecodeSiz);                            // in
+      pDecode, nDecodeSiz);                               // in
 
    if (nBytesDecoded < 0)
    {
@@ -650,6 +699,7 @@
 {
 
    size_t pos = 0;
+   // Find the stream index in mScs array
    int streamid = -1;
    for (int i = 0; i < mNumStreams; i++)
    {
@@ -659,29 +709,34 @@
          break;
       }
    }
+   // Stream is not found. This should not really happen
    if (streamid == -1)
    {
       return 1;
    }
 
+   // Allocate the buffer to store audio.
    int nChannels = sc->m_stream->codec->channels < sc->m_initialchannels ? 
sc->m_stream->codec->channels : sc->m_initialchannels;
    int16_t **tmp = (int16_t**)malloc(sizeof(short*)*nChannels);
    for (int chn = 0; chn < nChannels; chn++)
    {
-      tmp[chn] = 
(int16_t*)malloc(sizeof(int16_t)*sc->m_decodedAudioSamplesValidSiz/sizeof(int16_t)/nChannels);
+      tmp[chn] = 
(int16_t*)malloc(sizeof(int16_t)*sc->m_decodedAudioSamplesValidSiz/sizeof(int16_t)/sc->m_stream->codec->channels);
    }
 
+   // Separate the channels
    int index = 0;
    while (pos < sc->m_decodedAudioSamplesValidSiz/sizeof(int16_t))
    {
-      for (int chn=0; chn < nChannels; chn++)
+      for (int chn=0; chn < sc->m_stream->codec->channels; chn++)
       {
-         tmp[chn][index] = sc->m_decodedAudioSamples[pos];
+         if (chn < nChannels)
+            tmp[chn][index] = sc->m_decodedAudioSamples[pos];
          pos++;
       }
       index++;
    }
 
+   // Write audio into WaveTracks
    for (int chn=0; chn < nChannels; chn++)
    {
       mChannels[streamid][chn]->Append((samplePtr)tmp[chn],int16Sample,index);
@@ -690,6 +745,7 @@
 
    free(tmp);
    
+   // Try to update the progress indicator (and see if user wants to cancel)
    int tsize = FFmpegLibsInst->url_fsize(mFormatContext->pb);
    if (!mProgress->Update((wxLongLong)this->mFormatContext->pb->pos, 
(wxLongLong)(tsize > 0 ? tsize : 1))) {
       mCancelled = true;
@@ -701,10 +757,10 @@
 
 void FFmpegImportFileHandle::WriteMetadata(AVFormatContext *avf,Tags *tags)
 {
-
    tags->Clear();
 
-
+   // We are assuming that tags are in UTF8.
+   // TODO: for some formats tags are not in UTF8. Detect and handle that.
    tags->SetTag(TAG_TITLE,wxString::FromUTF8(avf->title));
    tags->SetTag(TAG_ARTIST,wxString::FromUTF8(avf->author));
    //tags->SetTag(TAG_COPYRIGHT,avf->copyright);
@@ -713,7 +769,6 @@
    tags->SetTag(TAG_YEAR,avf->year);
    tags->SetTag(TAG_TRACK,avf->track);
    tags->SetTag(TAG_GENRE,wxString::FromUTF8(avf->genre));
-
 }
 
 


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Audacity-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/audacity-cvs

Reply via email to