Skip to content

Commit

Permalink
transcode: support encode start time
Browse files Browse the repository at this point in the history
  • Loading branch information
wang-bin committed Dec 28, 2015
1 parent f73e538 commit a56136a
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 8 deletions.
23 changes: 22 additions & 1 deletion examples/simpletranscode/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qDebug("QtAV simpletranscode");
qDebug("./simpletranscode -i infile -o outfile [-c:v video_codec (default: libx264)] [-f format]");
qDebug("./simpletranscode -i infile -o outfile [-c:v video_codec (default: libx264)] [-f format] [-an] [-ss HH:mm:ss.z]");
qDebug("-an: disable audio");
qDebug() << "examples:\n"
<< "./simpletranscode -i test.mp4 -o /tmp/test-%05d.png -f image2 -c:v png\n"
<< "./simpletranscode -i test.mp4 -o /tmp/bbb%04d.ts -f segment\n"
Expand Down Expand Up @@ -61,6 +62,14 @@ int main(int argc, char *argv[])
idx = a.arguments().indexOf(QLatin1String("-f"));
if (idx > 0)
fmt = a.arguments().at(idx + 1);
bool an = false;
idx = a.arguments().indexOf(QLatin1String("-an"));
if (idx > 0)
an = true;
qint64 ss = 0;
idx = a.arguments().indexOf(QLatin1String("-ss"));
if (idx > 0)
ss = QTime(0, 0, 0).msecsTo(QTime::fromString(a.arguments().at(idx + 1), QLatin1String("HH:mm:ss.z")));
QVariantHash muxopt, avfopt;
avfopt[QString::fromLatin1("segment_time")] = 4;
avfopt[QString::fromLatin1("segment_list_size")] = 0;
Expand All @@ -73,6 +82,8 @@ int main(int argc, char *argv[])
player.setFrameRate(1000.0); // as fast as possible
player.audio()->setBackends(QStringList() << QString::fromLatin1("null"));
AVTranscoder avt;
if (ss > 0)
avt.setStartTime(ss);
avt.setMediaSource(&player);
avt.setOutputMedia(outFile);
avt.setOutputOptions(muxopt);
Expand All @@ -87,6 +98,16 @@ int main(int argc, char *argv[])
venc->setBitRate(1024*1024);
if (fmt == QLatin1String("image2"))
venc->setPixelFormat(VideoFormat::Format_RGBA32);
if (an) {
avt.sourcePlayer()->setAudioStream(-1);
} else {
if (!avt.createAudioEncoder()) {
qWarning("Failed to create audio encoder");
return 1;
}
AudioEncoder *aenc = avt.audioEncoder();
aenc->setCodecName(ca);
}

QObject::connect(&avt, SIGNAL(stopped()), qApp, SLOT(quit()));
avt.start(); //start transcoder first
Expand Down
25 changes: 24 additions & 1 deletion src/AVTranscoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class AVTranscoder::Private
Private()
: started(false)
, encoded_frames(0)
, start_time(0)
, source_player(0)
, afilter(0)
, vfilter(0)
Expand All @@ -52,6 +53,7 @@ class AVTranscoder::Private

bool started;
int encoded_frames;
qint64 start_time;
AVPlayer *source_player;
AudioEncodeFilter *afilter;
VideoEncodeFilter *vfilter;
Expand Down Expand Up @@ -194,6 +196,23 @@ bool AVTranscoder::isPaused() const
return false; //stopped
}

qint64 AVTranscoder::startTime() const
{
return d->start_time;
}

void AVTranscoder::setStartTime(qint64 ms)
{
if (d->start_time == ms)
return;
d->start_time = ms;
Q_EMIT startTimeChanged(ms);
if (d->afilter)
d->afilter->setStartTime(startTime());
if (d->vfilter)
d->vfilter->setStartTime(startTime());
}

void AVTranscoder::start()
{
if (!videoEncoder())
Expand All @@ -204,9 +223,11 @@ void AVTranscoder::start()
d->started = true;
if (sourcePlayer()) {
if (d->afilter) {
d->afilter->setStartTime(startTime());
sourcePlayer()->installFilter(d->afilter);
}
if (d->vfilter) {
d->vfilter->setStartTime(startTime());
qDebug("framerate: %.3f/%.3f", videoEncoder()->frameRate(), sourcePlayer()->statistics().video.frame_rate);
if (videoEncoder()->frameRate() <= 0) { // use source frame rate. set before install filter (so before open)
videoEncoder()->setFrameRate(sourcePlayer()->statistics().video.frame_rate);
Expand Down Expand Up @@ -273,8 +294,10 @@ void AVTranscoder::prepareMuxer()
{
// open muxer only if all encoders are open
if (audioEncoder() && videoEncoder()) {
if (!audioEncoder()->isOpen() || !videoEncoder()->isOpen())
if (!audioEncoder()->isOpen() || !videoEncoder()->isOpen()) {
qDebug("encoders are not readly a:%d v:%d", audioEncoder()->isOpen(), videoEncoder()->isOpen());
return;
}
}
if (audioEncoder())
d->muxer.copyProperties(audioEncoder());
Expand Down
8 changes: 8 additions & 0 deletions src/QtAV/AVTranscoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,20 @@ class Q_AV_EXPORT AVTranscoder : public QObject
qreal startTimestamp() const;
qreal encodedDuration() const;

/*!
* \brief startTime
* Start to encode after startTime(). To decode from a given time, call sourcePlayer()->setPosition()
*/
qint64 startTime() const;
void setStartTime(qint64 ms);

Q_SIGNALS:
void videoFrameEncoded(qreal timestamp);
void audioFrameEncoded(qreal timestamp);
void started();
void stopped();
void paused(bool value);
void startTimeChanged(qint64 ms);

public Q_SLOTS:
void start();
Expand Down
16 changes: 14 additions & 2 deletions src/QtAV/EncodeFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ class Q_AV_EXPORT AudioEncodeFilter : public AudioFilter
AudioEncoder* encoder() const;
// TODO: async property

/*!
* \brief startTime
* start to encode after startTime()
*/
qint64 startTime() const;
void setStartTime(qint64 value);
Q_SIGNALS:
/*!
* \brief readyToEncode
Expand All @@ -62,7 +68,7 @@ class Q_AV_EXPORT AudioEncodeFilter : public AudioFilter
*/
void readyToEncode();
void frameEncoded(const QtAV::Packet& packet);

void startTimeChanged(qint64 value);
protected:
virtual void process(Statistics* statistics, AudioFrame* frame = 0) Q_DECL_OVERRIDE;
void encode(const AudioFrame& frame = AudioFrame());
Expand Down Expand Up @@ -93,6 +99,12 @@ class Q_AV_EXPORT VideoEncodeFilter : public VideoFilter
VideoEncoder* encoder() const;
// TODO: async property

/*!
* \brief startTime
* start to encode after startTime()
*/
qint64 startTime() const;
void setStartTime(qint64 value);
Q_SIGNALS:
/*!
* \brief readyToEncode
Expand All @@ -101,7 +113,7 @@ class Q_AV_EXPORT VideoEncodeFilter : public VideoFilter
*/
void readyToEncode();
void frameEncoded(const QtAV::Packet& packet);

void startTimeChanged(qint64 value);
protected:
virtual void process(Statistics* statistics, VideoFrame* frame = 0) Q_DECL_OVERRIDE;
void encode(const VideoFrame& frame = VideoFrame());
Expand Down
43 changes: 39 additions & 4 deletions src/filter/EncodeFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace QtAV {
class AudioEncodeFilterPrivate Q_DECL_FINAL : public AudioFilterPrivate
{
public:
AudioEncodeFilterPrivate() : enc(0) {}
AudioEncodeFilterPrivate() : enc(0), start_time(0) {}
~AudioEncodeFilterPrivate() {
if (enc) {
enc->close();
Expand All @@ -39,6 +39,7 @@ class AudioEncodeFilterPrivate Q_DECL_FINAL : public AudioFilterPrivate
}

AudioEncoder* enc;
qint64 start_time;
};

AudioEncodeFilter::AudioEncodeFilter(QObject *parent)
Expand All @@ -62,6 +63,20 @@ AudioEncoder* AudioEncodeFilter::encoder() const
return d_func().enc;
}

qint64 AudioEncodeFilter::startTime() const
{
return d_func().start_time;
}

void AudioEncodeFilter::setStartTime(qint64 value)
{
DPTR_D(AudioEncodeFilter);
if (d.start_time == value)
return;
d.start_time = value;
Q_EMIT startTimeChanged(value);
}

void AudioEncodeFilter::process(Statistics *statistics, AudioFrame *frame)
{
Q_UNUSED(statistics);
Expand All @@ -78,8 +93,9 @@ void AudioEncodeFilter::encode(const AudioFrame& frame)
#if 0 //TODO: if set the input format, check whether it is supported in open()
if (!d.enc->audioFormat().isValid()) {
AudioFormat af(frame.format());
if (af.isPlanar())
af.setSampleFormat(AudioFormat::packedSampleFormat(af.sampleFormat()));
//if (af.isPlanar())
// af.setSampleFormat(AudioFormat::packedSampleFormat(af.sampleFormat()));
af.setSampleFormat(AudioFormat::SampleFormat_Unknown);
d.enc->setAudioFormat(af);
}
#endif
Expand All @@ -89,6 +105,8 @@ void AudioEncodeFilter::encode(const AudioFrame& frame)
}
Q_EMIT readyToEncode();
}
if (frame.timestamp()*1000.0 < startTime())
return;
// TODO: async
AudioFrame f(frame);
if (f.format() != d.enc->audioFormat())
Expand All @@ -104,7 +122,7 @@ void AudioEncodeFilter::encode(const AudioFrame& frame)
class VideoEncodeFilterPrivate Q_DECL_FINAL : public VideoFilterPrivate
{
public:
VideoEncodeFilterPrivate() : enc(0) {}
VideoEncodeFilterPrivate() : enc(0), start_time(0) {}
~VideoEncodeFilterPrivate() {
if (enc) {
enc->close();
Expand All @@ -113,6 +131,7 @@ class VideoEncodeFilterPrivate Q_DECL_FINAL : public VideoFilterPrivate
}

VideoEncoder* enc;
qint64 start_time;
};

VideoEncodeFilter::VideoEncodeFilter(QObject *parent)
Expand All @@ -136,6 +155,20 @@ VideoEncoder* VideoEncodeFilter::encoder() const
return d_func().enc;
}

qint64 VideoEncodeFilter::startTime() const
{
return d_func().start_time;
}

void VideoEncodeFilter::setStartTime(qint64 value)
{
DPTR_D(VideoEncodeFilter);
if (d.start_time == value)
return;
d.start_time = value;
Q_EMIT startTimeChanged(value);
}

void VideoEncodeFilter::process(Statistics *statistics, VideoFrame *frame)
{
Q_UNUSED(statistics);
Expand All @@ -161,6 +194,8 @@ void VideoEncodeFilter::encode(const VideoFrame& frame)
qWarning("Frame size (%dx%d) and video encoder size (%dx%d) mismatch! Close encoder please.", d.enc->width(), d.enc->height(), frame.width(), frame.height());
return;
}
if (frame.timestamp()*1000.0 < startTime())
return;
// TODO: async
VideoFrame f(frame);
if (f.pixelFormat() != d.enc->pixelFormat())
Expand Down

0 comments on commit a56136a

Please sign in to comment.