Ejemplo n.º 1
0
 AVPacket* Stream::popEncodedData()
 {
     AVPacket* result = nullptr;
     sf::Lock l(m_readerMutex);
     
     if (!m_packetList.size() && !isPassive())
     {
         m_dataSource.requestMoreData(*this);
     }
     
     if (m_packetList.size())
     {
         result = m_packetList.front();
         m_packetList.pop_front();
     }
     else
     {
         if (m_stream->codec->codec->capabilities & CODEC_CAP_DELAY)
         {
             AVPacket* flushPacket = (AVPacket*)av_malloc(sizeof(*flushPacket));
             av_init_packet(flushPacket);
             flushPacket->data = nullptr;
             flushPacket->size = 0;
             result = flushPacket;
             
             sfeLogDebug("Sending flush packet: " + mediaTypeToString(getStreamKind()));
         }
     }
     
     return result;
 }
Ejemplo n.º 2
0
 bool SubtitleStream::onGetData()
 {
     AVPacket* packet = popEncodedData();
     AVSubtitle sub;
     int32_t gotSub = 0;
     uint32_t goOn = 0;
     int64_t pts = 0;
     
     if (packet)
     {
         goOn = 1;
         
         while (!gotSub && packet && goOn)
         {
             bool needsMoreDecoding = false;
             
             CHECK(packet != nullptr, "inconsistency error");
             goOn = avcodec_decode_subtitle2(m_stream->codec, &sub, &gotSub, packet);
             
             pts = 0;
             if (packet->pts != AV_NOPTS_VALUE)
                 pts = packet->pts;
             
             if (gotSub && pts)
             {
                 bool succeeded = false;
                 std::shared_ptr<SubtitleData> sfeSub = std::make_shared<SubtitleData>(&sub, succeeded);
                 
                 if (succeeded)
                     m_pendingSubtitles.push_back(sfeSub);
             }
             
             if (needsMoreDecoding)
             {
                 prependEncodedData(packet);
             }
             else
             {
                 av_free_packet(packet);
                 av_free(packet);
             }
             
             if (!gotSub && goOn)
             {
                 sfeLogDebug("no subtitle in this packet, reading further");
                 packet = popEncodedData();
             }
         }
     }
     return (goOn != 0);
 }
Ejemplo n.º 3
0
 Demuxer::Demuxer(const std::string& sourceFile, std::shared_ptr<Timer> timer,
                  VideoStream::Delegate& videoDelegate, SubtitleStream::Delegate& subtitleDelegate) :
 m_formatCtx(nullptr),
 m_eofReached(false),
 m_streams(),
 m_ignoredStreams(),
 m_synchronized(),
 m_timer(timer),
 m_connectedAudioStream(nullptr),
 m_connectedVideoStream(nullptr),
 m_connectedSubtitleStream(nullptr),
 m_duration(sf::Time::Zero)
 {
     CHECK(sourceFile.size(), "Demuxer::Demuxer() - invalid argument: sourceFile");
     CHECK(timer, "Inconsistency error: null timer");
     
     int err = 0;
     
     // Load all the decoders
     loadFFmpeg();
     
     // Open the movie file
     err = avformat_open_input(&m_formatCtx, sourceFile.c_str(), nullptr, nullptr);
     CHECK0(err, "Demuxer::Demuxer() - error while opening media: " + sourceFile);
     CHECK(m_formatCtx, "Demuxer() - inconsistency: media context cannot be nullptr");
     
     // Read the general movie informations
     err = avformat_find_stream_info(m_formatCtx, nullptr);
     CHECK0(err, "Demuxer::Demuxer() - error while retreiving media information");
     
     // Get the media duration if possible (otherwise rely on the streams)
     if (m_formatCtx->duration != AV_NOPTS_VALUE)
     {
         int64_t secs, us;
         secs = m_formatCtx->duration / AV_TIME_BASE;
         us = m_formatCtx->duration % AV_TIME_BASE;
         m_duration = sf::seconds(secs + (float)us / AV_TIME_BASE);
     }
     
     // Find all interesting streams
     for (unsigned int i = 0; i < m_formatCtx->nb_streams; i++)
     {
         AVStream* & ffstream = m_formatCtx->streams[i];
         
         try
         {
             std::shared_ptr<Stream> stream;
             
             switch (ffstream->codec->codec_type)
             {
                 case AVMEDIA_TYPE_VIDEO:
                     stream = std::make_shared<VideoStream>(m_formatCtx, ffstream, *this, timer, videoDelegate);
                     
                     if (m_duration == sf::Time::Zero)
                     {
                         extractDurationFromStream(ffstream);
                     }
                     
                     sfeLogDebug("Loaded " + avcodec_get_name(ffstream->codec->codec_id) + " video stream");
                     break;
                     
                 case AVMEDIA_TYPE_AUDIO:
                     stream = std::make_shared<AudioStream>(m_formatCtx, ffstream, *this, timer);
                     
                     if (m_duration == sf::Time::Zero)
                     {
                         extractDurationFromStream(ffstream);
                     }
                     
                     sfeLogDebug("Loaded " + avcodec_get_name(ffstream->codec->codec_id) + " audio stream");
                     break;
                 case AVMEDIA_TYPE_SUBTITLE:
                     stream = std::make_shared<SubtitleStream>(m_formatCtx, ffstream, *this, timer, subtitleDelegate);
                     
                     sfeLogDebug("Loaded " + avcodec_get_name(ffstream->codec->codec_id) + " subtitle stream");
                     break;
                 default:
                     m_ignoredStreams[ffstream->index] = Stream::AVStreamDescription(ffstream);
                     sfeLogDebug(m_ignoredStreams[ffstream->index] + " ignored");
                     break;
             }
             
             // Don't create an entry in the map unless everything went well and stream did not get ignored
             if (stream)
                 m_streams[ffstream->index] = stream;
         }
         catch (std::runtime_error& e)
         {
             std::string streamDesc = Stream::AVStreamDescription(ffstream);
             
             sfeLogError("error while loading " + streamDesc + ": " + e.what());
             CHECK(m_streams.find(ffstream->index) == m_streams.end(),
                   "Internal inconcistency error: stream whose loading failed should not be stored");
         }
     }
     
     if (m_duration == sf::Time::Zero)
     {
         sfeLogWarning("The media duration could not be retreived");
     }
     
     m_timer->addObserver(*this, DemuxerTimerPriority);
 }