Rotation from metadata supported in FFmpeg video stream reader.

Also small glitch fix in settings rebuild after self() has changed.
This commit is contained in:
John Preston 2016-09-26 10:58:04 +03:00
parent ff3e6c429d
commit 866bc4ff8a
3 changed files with 45 additions and 0 deletions

View File

@ -209,6 +209,9 @@ bool FFMpegReaderImplementation::renderFrame(QImage &to, bool &hasAlpha, const Q
}
QSize toSize(size.isEmpty() ? QSize(_width, _height) : size);
if (!size.isEmpty() && rotationSwapWidthHeight()) {
toSize.transpose();
}
if (to.isNull() || to.size() != toSize) {
to = QImage(toSize, QImage::Format_ARGB32);
}
@ -231,6 +234,15 @@ bool FFMpegReaderImplementation::renderFrame(QImage &to, bool &hasAlpha, const Q
return false;
}
}
if (_rotation != Rotation::None) {
QTransform rotationTransform;
switch (_rotation) {
case Rotation::Degrees90: rotationTransform.rotate(90); break;
case Rotation::Degrees180: rotationTransform.rotate(180); break;
case Rotation::Degrees270: rotationTransform.rotate(270); break;
}
to = to.transformed(rotationTransform);
}
// Read some future packets for audio stream.
if (_audioStreamId >= 0) {
@ -247,6 +259,15 @@ bool FFMpegReaderImplementation::renderFrame(QImage &to, bool &hasAlpha, const Q
return true;
}
FFMpegReaderImplementation::Rotation FFMpegReaderImplementation::rotationFromDegrees(int degrees) const {
switch (degrees) {
case 90: return Rotation::Degrees90;
case 180: return Rotation::Degrees180;
case 270: return Rotation::Degrees270;
}
return Rotation::None;
}
bool FFMpegReaderImplementation::start(Mode mode, int64 &positionMs) {
_mode = mode;
@ -286,6 +307,16 @@ bool FFMpegReaderImplementation::start(Mode mode, int64 &positionMs) {
}
_packetNull.stream_index = _streamId;
auto rotateTag = av_dict_get(_fmtContext->streams[_streamId]->metadata, "rotate", NULL, 0);
if (rotateTag && *rotateTag->value) {
auto stringRotateTag = QString::fromUtf8(rotateTag->value);
auto toIntSucceeded = false;
auto rotateDegrees = stringRotateTag.toInt(&toIntSucceeded);
if (toIntSucceeded) {
_rotation = rotationFromDegrees(rotateDegrees);
}
}
_codecContext = avcodec_alloc_context3(nullptr);
if (!_codecContext) {
LOG(("Audio Error: Unable to avcodec_alloc_context3 %1").arg(logData()));

View File

@ -71,6 +71,17 @@ private:
int64 countPacketMs(AVPacket *packet) const;
PacketResult readAndProcessPacket();
enum class Rotation {
None,
Degrees90,
Degrees180,
Degrees270,
};
Rotation rotationFromDegrees(int degrees) const;
bool rotationSwapWidthHeight() const {
return (_rotation == Rotation::Degrees90) || (_rotation == Rotation::Degrees270);
}
void startPacket();
void finishPacket();
void clearPacketQueue();
@ -80,6 +91,8 @@ private:
Mode _mode = Mode::Normal;
Rotation _rotation = Rotation::None;
uchar *_ioBuffer = nullptr;
AVIOContext *_ioContext = nullptr;
AVFormatContext *_fmtContext = nullptr;

View File

@ -59,6 +59,7 @@ void InnerWidget::selfUpdated() {
void InnerWidget::refreshBlocks() {
_cover.destroyDelayed();
for_const (auto block, _blocks) {
block->hide();
block->deleteLater();
}
_blocks.clear();