int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QString file = "test.avi"; int idx = a.arguments().indexOf("-f"); if (idx > 0) file = a.arguments().at(idx + 1); QString decName("FFmpeg"); idx = a.arguments().indexOf("-vc"); if (idx > 0) decName = a.arguments().at(idx + 1); VideoDecoderId cid = VideoDecoderFactory::id(decName.toStdString()); if (cid <= 0) { qWarning("Can not find decoder: %s", decName.toUtf8().constData()); return 1; } VideoDecoder *dec = VideoDecoderFactory::create(cid); AVDemuxer demux; if (!demux.loadFile(file)) { qWarning("Failed to load file: %s", file.toUtf8().constData()); return 1; } dec->setCodecContext(demux.videoCodecContext()); dec->prepare(); dec->open(); QElapsedTimer timer; timer.start(); int count = 0; VideoFrame frame; while (!demux.atEnd()) { if (!demux.readFrame()) continue; if (dec->decode(demux.packet()->data)) { /* * TODO: may contains more than 1 frames * map from gpu or not? */ //frame = dec->frame().clone(); count++; } } qint64 elapsed = timer.elapsed(); int msec = elapsed/1000LL; qDebug("decoded frames: %d, time: %d, average speed: %d", count, msec, count/msec); return 0; }
int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); qDebug() << QLatin1String("usage: ") << a.applicationFilePath().split(QLatin1String("/")).last().append(QLatin1String(" url")); if (a.arguments().size() < 2) return 0; QScopedPointer<AudioOutput> ao(new AudioOutput()); AVDemuxer demuxer; demuxer.setMedia(a.arguments().last()); if (!demuxer.load()) { qWarning() << "Failed to load file " << demuxer.fileName(); return 1; } QScopedPointer<AudioDecoder> dec(AudioDecoder::create()); // delete by user dec->setCodecContext(demuxer.audioCodecContext()); //dec->prepare(); if (!dec->open()) qFatal("open decoder error"); int astream = demuxer.audioStream(); Packet pkt; while (!demuxer.atEnd()) { if (!pkt.isValid()) { // continue to decode previous undecoded data if (!demuxer.readFrame() || demuxer.stream() != astream) continue; pkt = demuxer.packet(); } if (!dec->decode(pkt)) { pkt = Packet(); // set invalid to read from demuxer continue; } // decode the rest data in the next loop. read from demuxer if no data remains pkt.data = QByteArray::fromRawData(pkt.data.constData() + pkt.data.size() - dec->undecodedSize(), dec->undecodedSize()); AudioFrame frame(dec->frame()); // why is faster to call frame() for hwdec? no frame() is very slow for VDA if (!frame) continue; //frame.setAudioResampler(dec->resampler()); // if not set, always create a resampler in AudioFrame.to() AudioFormat af(frame.format()); if (ao->isOpen()) { af = ao->audioFormat(); } else { dec->resampler()->setOutAudioFormat(af); // if decoded format is not supported by audio renderer, change decoder output format if (!ao->isSupported(af)) { af.setSampleFormat(ao->preferredSampleFormat()); af.setChannelLayout(ao->preferredChannelLayout()); dec->resampler()->setOutAudioFormat(af); dec->resampler()->prepare(); } // now af is supported by audio renderer. it's safe to open ao->setAudioFormat(af); if (!ao->open()) qFatal("Open audio output error"); #if 0 // always resample ONCE due to QtAV bug // the first format unsupported frame still need to be converted to a supported format if (!ao->isSupported(frame.format())) frame = frame.to(af); #endif qDebug() << "Input: " << frame.format(); qDebug() << "Output: " << af; } printf("playing: %.3f...\r", frame.timestamp()); fflush(0); // always resample ONCE. otherwise data are all 0x0. QtAV bug frame = frame.to(af); QByteArray data(frame.data()); // plane data. currently only packet sample formats are supported. while (!data.isEmpty()) { ao->play(QByteArray::fromRawData(data.constData(), qMin(data.size(), ao->bufferSize()))); data.remove(0, qMin(data.size(), ao->bufferSize())); } } // dec, ao will be closed in dtor. demuxer will call unload in dtor return 0; }