diff -r 3331b30e4ef1 -r 88fde28bbda6 QTfrontend/util/libav_iteraction.cpp --- a/QTfrontend/util/libav_iteraction.cpp Sun Oct 21 01:28:33 2012 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,358 +0,0 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2012 Andrey Korotaev - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "libav_iteraction.h" - -#if VIDEOREC -#define __STDC_CONSTANT_MACROS -extern "C" -{ -#include "libavformat/avformat.h" -} - -#include -#include -#include -#include - -#include "HWApplication.h" - -struct Codec -{ - CodecID id; - bool isAudio; - QString shortName; // used for identification - QString longName; // used for displaying to user - bool isRecomended; -}; - -struct Format -{ - QString shortName; - QString longName; - bool isRecomended; - QString extension; - QVector codecs; -}; - -QList codecs; -QMap formats; - -// test if given format supports given codec -bool FormatQueryCodec(AVOutputFormat *ofmt, enum CodecID codec_id) -{ -#if LIBAVFORMAT_VERSION_MAJOR >= 54 - return avformat_query_codec(ofmt, codec_id, FF_COMPLIANCE_NORMAL) == 1; -#else - if (ofmt->codec_tag) - return !!av_codec_get_tag(ofmt->codec_tag, codec_id); - return codec_id == ofmt->video_codec || codec_id == ofmt->audio_codec; -#endif -} - -LibavIteraction::LibavIteraction() : QObject() -{ - // initialize libav and register all codecs and formats - av_register_all(); - - // get list of all codecs - AVCodec* pCodec = NULL; - while (pCodec = av_codec_next(pCodec)) - { -#if LIBAVCODEC_VERSION_MAJOR >= 54 - if (!av_codec_is_encoder(pCodec)) -#else - if (!pCodec->encode) -#endif - continue; - - if (pCodec->type != AVMEDIA_TYPE_VIDEO && pCodec->type != AVMEDIA_TYPE_AUDIO) - continue; - - // this encoders seems to be buggy - if (strcmp(pCodec->name, "rv10") == 0 || strcmp(pCodec->name, "rv20") == 0) - continue; - - // doesn't support stereo sound - if (strcmp(pCodec->name, "real_144") == 0) - continue; - - if (!pCodec->long_name || strlen(pCodec->long_name) == 0) - continue; - - if (pCodec->type == AVMEDIA_TYPE_VIDEO) - { - if (pCodec->supported_framerates != NULL) - continue; - - // check if codec supports yuv 4:2:0 format - if (!pCodec->pix_fmts) - continue; - bool yuv420Supported = false; - for (const PixelFormat* pfmt = pCodec->pix_fmts; *pfmt != -1; pfmt++) - if (*pfmt == PIX_FMT_YUV420P) - { - yuv420Supported = true; - break; - } - if (!yuv420Supported) - continue; - } - if (pCodec->type == AVMEDIA_TYPE_AUDIO) - { - // check if codec supports signed 16-bit format - if (!pCodec->sample_fmts) - continue; - bool s16Supported = false; - for (const AVSampleFormat* pfmt = pCodec->sample_fmts; *pfmt != -1; pfmt++) - if (*pfmt == AV_SAMPLE_FMT_S16) - { - s16Supported = true; - break; - } - if (!s16Supported) - continue; - } - // add codec to list of codecs - codecs.push_back(Codec()); - Codec & codec = codecs.back(); - codec.id = pCodec->id; - codec.isAudio = pCodec->type == AVMEDIA_TYPE_AUDIO; - codec.shortName = pCodec->name; - codec.longName = pCodec->long_name; - - codec.isRecomended = false; - if (strcmp(pCodec->name, "libx264") == 0) - { - codec.longName = "H.264/MPEG-4 Part 10 AVC (x264)"; - codec.isRecomended = true; - } - else if (strcmp(pCodec->name, "libxvid") == 0) - { - codec.longName = "MPEG-4 Part 2 (Xvid)"; - codec.isRecomended = true; - } - else if (strcmp(pCodec->name, "libmp3lame") == 0) - { - codec.longName = "MP3 (MPEG audio layer 3) (LAME)"; - codec.isRecomended = true; - } - else - codec.longName = pCodec->long_name; - - if (strcmp(pCodec->name, "mpeg4") == 0 || strcmp(pCodec->name, "ac3_fixed") == 0) - codec.isRecomended = true; - - // FIXME: remove next line - //codec.longName += QString(" (%1)").arg(codec.shortName); - } - - // get list of all formats - AVOutputFormat* pFormat = NULL; - while (pFormat = av_oformat_next(pFormat)) - { - if (!pFormat->extensions) - continue; - - // skip some strange formats to not confuse users - if (strstr(pFormat->long_name, "raw")) - continue; - - Format format; - bool hasVideoCodec = false; - for (QList::iterator codec = codecs.begin(); codec != codecs.end(); ++codec) - { - if (!FormatQueryCodec(pFormat, codec->id)) - continue; - format.codecs.push_back(&*codec); - if (!codec->isAudio) - hasVideoCodec = true; - } - if (!hasVideoCodec) - continue; - - QString ext(pFormat->extensions); - ext.truncate(strcspn(pFormat->extensions, ",")); - format.extension = ext; - format.shortName = pFormat->name; - format.longName = QString("%1 (*.%2)").arg(pFormat->long_name).arg(ext); - - // FIXME: remove next line - //format.longName += QString(" (%1)").arg(format.shortName); - - format.isRecomended = strcmp(pFormat->name, "mp4") == 0 || strcmp(pFormat->name, "avi") == 0; - - formats[pFormat->name] = format; - } -} - -void LibavIteraction::fillFormats(QComboBox * pFormats) -{ - // first insert recomended formats - foreach(const Format & format, formats) - if (format.isRecomended) - pFormats->addItem(format.longName, format.shortName); - - // remember where to place separator between recomended and other formats - int sep = pFormats->count(); - - // insert remaining formats - foreach(const Format & format, formats) - if (!format.isRecomended) - pFormats->addItem(format.longName, format.shortName); - - // insert separator if necessary - if (sep != 0 && sep != pFormats->count()) - pFormats->insertSeparator(sep); -} - -void LibavIteraction::fillCodecs(const QString & fmt, QComboBox * pVCodecs, QComboBox * pACodecs) -{ - Format & format = formats[fmt]; - - // first insert recomended codecs - foreach(Codec * codec, format.codecs) - { - if (codec->isRecomended) - { - if (codec->isAudio) - pACodecs->addItem(codec->longName, codec->shortName); - else - pVCodecs->addItem(codec->longName, codec->shortName); - } - } - - // remember where to place separators between recomended and other codecs - int vsep = pVCodecs->count(); - int asep = pACodecs->count(); - - // insert remaining codecs - foreach(Codec * codec, format.codecs) - { - if (!codec->isRecomended) - { - if (codec->isAudio) - pACodecs->addItem(codec->longName, codec->shortName); - else - pVCodecs->addItem(codec->longName, codec->shortName); - } - } - - // insert separators if necessary - if (vsep != 0 && vsep != pVCodecs->count()) - pVCodecs->insertSeparator(vsep); - if (asep != 0 && asep != pACodecs->count()) - pACodecs->insertSeparator(asep); -} - -QString LibavIteraction::getExtension(const QString & format) -{ - return formats[format].extension; -} - -// get information abaout file (duration, resolution etc) in multiline string -QString LibavIteraction::getFileInfo(const QString & filepath) -{ - AVFormatContext* pContext = NULL; - QByteArray utf8path = filepath.toUtf8(); - if (avformat_open_input(&pContext, utf8path.data(), NULL, NULL) < 0) - return ""; -#if LIBAFORMAT_VERSION_MAJOR < 54 - if (av_find_stream_info(pContext) < 0) -#else - if (avformat_find_stream_info(pContext, NULL) < 0) -#endif - return ""; - - int s = float(pContext->duration)/AV_TIME_BASE; - QString desc = QString(tr("Duration: %1m %2s\n")).arg(s/60).arg(s%60); - for (int i = 0; i < (int)pContext->nb_streams; i++) - { - AVStream* pStream = pContext->streams[i]; - if (!pStream) - continue; - AVCodecContext* pCodec = pContext->streams[i]->codec; - if (!pCodec) - continue; - - if (pCodec->codec_type == AVMEDIA_TYPE_VIDEO) - { - desc += QString(tr("Video: %1x%2, ")).arg(pCodec->width).arg(pCodec->height); - if (pStream->avg_frame_rate.den) - { - float fps = float(pStream->avg_frame_rate.num)/pStream->avg_frame_rate.den; - desc += QString(tr("%1 fps, ")).arg(fps, 0, 'f', 2); - } - } - else if (pCodec->codec_type == AVMEDIA_TYPE_AUDIO) - desc += tr("Audio: "); - else - continue; - AVCodec* pDecoder = avcodec_find_decoder(pCodec->codec_id); - desc += pDecoder? pDecoder->name : "unknown"; - desc += "\n"; - } - AVDictionaryEntry* pComment = av_dict_get(pContext->metadata, "comment", NULL, 0); - if (pComment) - desc += QString("\n") + pComment->value; -#if LIBAFORMAT_VERSION_MAJOR < 54 - av_close_input_file(pContext); -#else - avformat_close_input(&pContext); -#endif - return desc; -} - -#else -LibavIteraction::LibavIteraction() : QObject() -{ - -} - -void LibavIteraction::fillFormats(QComboBox * pFormats) -{ - Q_UNUSED(pFormats); -} - -void LibavIteraction::fillCodecs(const QString & format, QComboBox * pVCodecs, QComboBox * pACodecs) -{ - Q_UNUSED(format); - Q_UNUSED(pVCodecs); - Q_UNUSED(pACodecs); -} - -QString LibavIteraction::getExtension(const QString & format) -{ - Q_UNUSED(format); - - return QString(); -} - -QString LibavIteraction::getFileInfo(const QString & filepath) -{ - Q_UNUSED(filepath); - - return QString(); -} -#endif - -LibavIteraction & LibavIteraction::instance() -{ - static LibavIteraction instance; - return instance; -}