Media.cpp 7 KB
Newer Older
1
/*****************************************************************************
2
 * Media.cpp: Represents a basic container for media informations.
3
 *****************************************************************************
4
 * Copyright (C) 2008-2016 VideoLAN
5
 *
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
6
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
7
 *          Yikei Lu    <luyikei.qmltu@gmail.com>
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * 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; either version 2
 * of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

24
/** \file
25
  * This file contains the Media class implementation.
26
  * It contains the Media meta-datas, and information to be used with a VLC Media.
27 28 29
  * It's used by the Library
  */

30 31 32 33
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

34
#include <QUrl>
35
#include <QVariant>
36
#include <QFileInfo>
37

38
#include "Media.h"
39 40

#include "Clip.h"
luyikei's avatar
luyikei committed
41 42
#include "Main/Core.h"
#include "Library/Library.h"
43
#include "Library/MediaLibrary.h"
44 45
#include "Tools/VlmcDebug.h"
#include "Project/Workspace.h"
46

47
const QString   Media::VideoExtensions = "*.avi *.3gp *.amv *.asf *.divx *.dv *.flv *.gxf "
48 49 50 51 52
                                         "*.iso *.m1v *.m2v *.m2t *.m2ts *.m4v *.mkv *.mov "
                                         "*.mp2 *.mp4 *.mpeg *.mpeg1 *.mpeg2 *.mpeg4 *.mpg "
                                         "*.mts *.mxf *.nsv *.nuv *.ogg *.ogm *.ogv *.ogx *.ps "
                                         "*.rec *.rm *.rmvb *.tod *.ts *.vob *.vro *.webm *.wmv";

53
const QString   Media::ImageExtensions = "*.png *.jpg *.jpeg";
54 55 56 57 58 59

const QString   Media::AudioExtensions = "*.a52 *.aac *.ac3 *.aiff *.amr *.aob *.ape "
                                         "*.dts *.flac *.it *.m4a *.m4p *.mid *.mka *.mlp "
                                         "*.mod *.mp1 *.mp2 *.mp3 *.mpc *.oga *.ogg *.oma "
                                         "*.rmi *.s3m *.spx *.tta *.voc *.vqf *.w64 *.wav "
                                         "*.wma *.wv *.xa *.xm";
60
const QString   Media::streamPrefix = "stream://";
61

Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
62
#ifdef HAVE_GUI
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
63
QPixmap*        Media::defaultSnapshot = nullptr;
64
#endif
65

Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
66
Media::Media( medialibrary::MediaPtr media, const QUuid& uuid /* = QUuid() */ )
luyikei's avatar
luyikei committed
67
    : m_input( nullptr )
68
    , m_mlMedia( media )
69
{
70 71 72 73 74 75 76 77 78 79 80
    auto files = media->files();
    Q_ASSERT( files.size() > 0 );
    for ( const auto& f : files )
    {
        if ( f->type() == medialibrary::IFile::Type::Main )
        {
            m_mlFile = f;
            break;
        }
    }
    if ( m_mlFile == nullptr )
81
        vlmcFatal( "No file representing media %s", media->title().c_str(), "was found" );
82
    m_input.reset( new Backend::MLT::MLTInput( m_mlFile->mrl().c_str() ) );
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
83
    m_baseClip = new Clip( sharedFromThis(), 0, Backend::IInput::EndOfMedia, uuid );
84 85
}

86 87
QString
Media::mrl() const
88
{
89
    return QString::fromStdString( m_mlFile->mrl() );
90 91
}

92 93
Media::FileType
Media::fileType() const
94
{
95 96 97 98 99 100 101 102 103 104
    switch ( m_mlMedia->type() )
    {
    case medialibrary::IMedia::Type::VideoType:
        return Video;
    case medialibrary::IMedia::Type::AudioType:
        return Audio;
    //FIXME: Unhandled Image type
    default:
        vlmcCritical() << "Unknown file type";
    }
105 106
}

107 108
QString
Media::title() const
109
{
110
    return QString::fromStdString( m_mlMedia->title() );
111
}
112

113 114 115 116 117 118
qint64
Media::id() const
{
    return m_mlMedia->id();
}

119 120 121
Clip*
Media::cut(qint64 begin, qint64 end)
{
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
122 123 124 125 126 127 128 129 130 131 132 133
    auto clip = new Clip( sharedFromThis(), begin, end );
    m_clips[clip->uuid()] = clip;
    emit subclipAdded( clip );
    return clip;
}

void
Media::removeSubclip(const QUuid& uuid)
{
    if ( m_clips.remove( uuid ) == 0 )
        return;
    emit subclipRemoved( uuid );
134 135
}

luyikei's avatar
luyikei committed
136 137 138
QVariant
Media::toVariant() const
{
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
139 140 141 142 143 144 145 146 147 148 149 150
    QVariantHash h = {
        { "uuid", m_baseClip->uuid() },
        { "mlId", static_cast<qlonglong>( m_mlMedia->id() ) }
    };
    if ( m_clips.isEmpty() == false )
    {
        QVariantList l;
        for ( const auto& c : m_clips.values() )
            l << c->toVariant();
        h.insert( "clips", l );
    }
    return QVariant( h );
luyikei's avatar
luyikei committed
151 152
}

luyikei's avatar
luyikei committed
153 154
Backend::IInput*
Media::input()
155
{
luyikei's avatar
luyikei committed
156
    return m_input.get();
157 158
}

luyikei's avatar
luyikei committed
159 160
const Backend::IInput*
Media::input() const
161
{
luyikei's avatar
luyikei committed
162
    return m_input.get();
163 164
}

165 166
QSharedPointer<Media>
Media::fromVariant( const QVariant& v )
167
{
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
    /**
     * The media is stored as such:
     * media: {
     *  mlId: <id>   // The media library ID
     *  uuid: <uuid> // The root clip UUID
     *  clips: [
     *    <clip 1>,  // The subclips
     *    ...
     *  ]
     * }
     */
    const auto& m = v.toMap();

    if ( m.contains( "mlId" ) == false || m.contains( "uuid" ) == false )
    {
        vlmcWarning() << "Invalid clip provided:" << m << "Missing 'mlId' and/or 'uuid' field(s)";
        return {};
    }
    auto mediaId = m["mlId"].toLongLong();
    auto uuid = m["uuid"].toUuid();
188
    auto mlMedia = Core::instance()->mediaLibrary()->media( mediaId );
189
    //FIXME: Is QSharedPointer exception safe in case its constructor throws an exception?
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
190 191 192 193 194 195 196 197 198 199 200 201
    auto media = QSharedPointer<Media>( new Media( mlMedia, uuid ) );

    // Now load the subclips:
    if ( m.contains( "clips" ) == false )
        return media;

    auto subclips = m["clips"].toList();
    for ( const auto& c : subclips )
    {
        media->loadSubclip( c.toMap() );
    }
    return media;
202
}
203

Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
204
#ifdef HAVE_GUI
205 206
QPixmap&
Media::snapshot()
207
{
luyikei's avatar
luyikei committed
208 209 210 211 212 213 214 215 216 217 218 219 220 221
    if ( Media::defaultSnapshot == nullptr )
        Media::defaultSnapshot = new QPixmap( ":/images/vlmc" );

    if ( m_snapshot.isNull() == true ) {
        int height = 200;
        int width = height * m_input->aspectRatio();
        m_input->setPosition( m_input->length() / 3 );
        QImage img( m_input->image( width, height ), width, height,
                    QImage::Format_RGBA8888, []( void* buf ){ delete[] (uchar*) buf; } );
        m_input->setPosition( 0 );
        m_snapshot.convertFromImage( img );
    }

    return m_snapshot.isNull() ? *Media::defaultSnapshot : m_snapshot;
222
}
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242

Clip*
Media::loadSubclip( const QVariantMap& m )
{
    if ( m.contains( "uuid" ) == false || m.contains( "begin" ) == false || m.contains( "end" ) == false )
    {
        vlmcWarning() << "Invalid clip provided:" << m;
        return nullptr;
    }
    const auto& uuid = m["uuid"].toUuid();
    const auto  begin = m["begin"].toLongLong();
    const auto  end = m["end"].toLongLong();
    auto clip = new Clip( sharedFromThis(), begin, end, uuid );
    //FIXME: This shouldn't be loaded from the library
    clip->loadFilters( m );

    m_clips[uuid] = clip;
    emit subclipAdded( clip );
    return clip;
}
243
#endif