Commits

Ivan Andrianov committed 42e46ac

Fixed AVFrame bug.

  • Participants
  • Parent commits 6c048e8
  • Branches devel

Comments (0)

Files changed (1)

File src/codecs/plugins/ffmpegdecoder/ffmpegdecoder.cpp

     Private();
     ~Private();
 
+    bool preparePacket();
+    bool prepareFrame();
     void initValues();
 
     bool openFile();
 
     AVPacket packet;
     int currentPacketSize;
-    AVFrame frame;
+    AVFrame * frame;
 
     bool readMetaData;
     bool readMetaDataSuccessful;
         av_register_all();
         avformat_network_init();
     }
-
     d->fileName = fileName;
     d->initValues();
 }
 {
     if(d->formatContext)
     {
-        if(d->frame.data[0])
+        if(d->frame)
         {
-            av_free(d->frame.data[0]);
+            av_free(d->frame);
         }
-
         if(d->codecContext && avcodec_is_open(d->codecContext))
         {
             avcodec_close(d->codecContext);
         }
-
         avformat_close_input(&d->formatContext);
     }
 }
     {
         return d->readMetaDataSuccessful;
     }
-
     d->readMetaData = true;
-
     if(!d->openFile() || !d->findStreamIndex() || !d->openCodec())
     {
         return false;
     }
-
     d->setMetaData();
-
     return true;
 }
 
 Frame * FFmpegDecoder::readFrame()
 {
-    if(!d->readMetaDataSuccessful)
+    if(!d->readMetaDataSuccessful || !d->prepareFrame())
     {
         return 0;
     }
-
     int gotFrame = false;
-
     while(!gotFrame)
     {
-        if(!d->packet.size)
+        if(!d->preparePacket())
         {
-            if(d->currentPacketSize)
-            {
-                d->packet.size = d->currentPacketSize;
-                d->packet.data -= d->currentPacketSize;
-                av_free_packet(&d->packet);
-            }
-
-            if(av_read_frame(d->formatContext, &d->packet) < 0)
-            {
-                return new Frame();
-            }
-
-            d->currentPacketSize = d->packet.size;
+            return new Frame();
         }
-
-        int readBytes = avcodec_decode_audio4(d->codecContext, &d->frame,
+        int readBytes = avcodec_decode_audio4(d->codecContext, d->frame,
                 &gotFrame, &d->packet);
-
         if(readBytes < 0)
         {
             return 0;
         }
-
         d->packet.size -= readBytes;
         d->packet.data += readBytes;
     }
-
     return d->processFrame();
 }
 
 {
 }
 
+bool FFmpegDecoder::Private::preparePacket()
+{
+    if(!packet.size)
+    {
+        if(currentPacketSize)
+        {
+            packet.size = currentPacketSize;
+            packet.data -= currentPacketSize;
+            av_free_packet(&packet);
+        }
+        if(av_read_frame(formatContext, &packet) < 0)
+        {
+            return false;
+        }
+        currentPacketSize = packet.size;
+    }
+    return true;
+}
+
+bool FFmpegDecoder::Private::prepareFrame()
+{
+    if(frame)
+    {
+        avcodec_get_frame_defaults(frame);
+        return true;
+    }
+    else
+    {
+        return (frame = avcodec_alloc_frame());
+    }
+}
+
 void FFmpegDecoder::Private::initValues()
 {
     formatContext = 0;
     codecContext = 0;
     codec = 0;
     streamIndex = -1;
-
     bitRate = 0;
-
     packet.size = 0;
     currentPacketSize = 0;
-    frame.data[0] = 0;
-    frame.linesize[0] = 0;
-
+    frame = 0;
     readMetaData = false;
     readMetaDataSuccessful = false;
 }
             break;
         }
     }
-
     return streamIndex >= 0;
 }
 
 bool FFmpegDecoder::Private::openCodec()
 {
     AVCodec * codec = avcodec_find_decoder(codecContext->codec_id);
-
     if(!codec || avcodec_open2(codecContext, codec, 0) < 0)
     {
         return false;
     }
-
     this->codec = codec;
-
     return true;
 }
 
 {
     setCodecName();
     setBitRate();
-
     setBytesPerSample();
     setSampleRate();
     setChannelCount();
-
     setArtistName();
     setAlbumName();
     setYear();
     setTrackName();
     setTrackNumber();
-
     readMetaDataSuccessful = true;
 }
 
 
 Frame * FFmpegDecoder::Private::processFrame()
 {
-    int sampleCount = frame.nb_samples;
+    int sampleCount = frame->nb_samples;
     int channelCount = codecContext->channels;
     int size = sampleCount * channelCount;
     qint32 * samples = new qint32[size];
-
     for(int i = 0; i < size; i++)
     {
         if(codecContext->sample_fmt == AV_SAMPLE_FMT_U8)
         {
-            samples[i] = ((qint8 *) frame.data[0])[i] - 128;
+            samples[i] = ((qint8 *) frame->data[0])[i] - 128;
         }
         else if(codecContext->sample_fmt == AV_SAMPLE_FMT_S16)
         {
-            samples[i] = ((qint16 *) frame.data[0])[i];
+            samples[i] = ((qint16 *) frame->data[0])[i];
         }
         else if(codecContext->sample_fmt == AV_SAMPLE_FMT_S32)
         {
-            samples[i] = ((qint32 *) frame.data[0])[i];
+            samples[i] = ((qint32 *) frame->data[0])[i];
         }
     }
-
     return new Frame(samples, sampleCount, channelCount);
 }