Transcode.cpp 8.75 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*****************************************************************************
 * Transcode.cpp :  File Transcoder
 *****************************************************************************
 * copyright (c) 2008-2009 the vlmc team
 *
 * authors: clement chavance <chavance.c@gmail.com>
 *
 * 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.
 *****************************************************************************/

//DEBUG
#include <QtDebug>
//DEBUG
26
#include <QApplication>
27
28
29
30
31
#include <QMessageBox>
#include <QFileDialog>
#include <QDir>
#include "Transcode.h"

Ludovic Fauvet's avatar
Ludovic Fauvet committed
32
static bool catchVLCException( libvlc_exception_t *ex )
33
{
Ludovic Fauvet's avatar
Ludovic Fauvet committed
34
    if ( libvlc_exception_raised( ex ) )
35
    {
36
        qDebug() << libvlc_errmsg();
Ludovic Fauvet's avatar
Ludovic Fauvet committed
37
        libvlc_exception_clear( ex );
38
39
40
41
42
        return (true);
    }
    return (false);
}

43
44
45
46
Transcode *Transcode::m_instance = NULL;

Transcode *Transcode::instance( QWidget *parent )
{
Ludovic Fauvet's avatar
Ludovic Fauvet committed
47
    if ( !Transcode::m_instance )
48
49
50
51
        Transcode::m_instance = new Transcode( parent );
    return ( Transcode::m_instance );
}

52
53
54
55
56
57
58
59
60
61
62
63
64
void Transcode::changeEvent( QEvent *e )
{
    switch ( e->type() )
    {
    case QEvent::LanguageChange:
        m_ui.retranslateUi( this );
        break;
    default:
        QWidget::changeEvent( e );
        break;
    }
}

65
Transcode::Transcode( QWidget *parent )
66
    : QDialog( parent ), m_running( false )
67
68
69
{
    m_ui.setupUi( this );
    //TODO : load every known profiles
70
71
72
73
74
75
    m_ui.profileSelector->addItem( tr( "H264 + AAC" ), "h264" );
    m_ui.profileSelector->addItem( tr( "Dirac + AAC" ), "dirac" );
    m_ui.profileSelector->addItem( tr( "Theora + Vorbis" ), "thVorbis" );
    m_ui.profileSelector->addItem( tr( "Theora + Flac" ), "thFlac" );
    m_ui.profileSelector->addItem( tr( "Mpeg4 + AAC" ), "mp4" );
    m_ui.profileSelector->addItem( tr( "WMV + WMA" ), "wmv" );
76
77
78
79
80
81
    QObject::connect( qApp,
                      SIGNAL( aboutToQuit() ),
                      this,
                      SLOT( deleteLater() ) );
}

82
83
84
85
86
87
void Transcode::on_browseFileButton_clicked()
{
    QString path = QFileDialog::getOpenFileName( this,
                                                 tr( "Choose File to open" ),
                                                 QDir::currentPath(),
                                                 tr( "Video files (*.avi *.mkv *.ogg)" ) );
88
    if ( path == "" )
89
90
91
92
93
        return ;
    m_origVidPath = path;
    m_ui.inputFileBox->setText( path );
}

94
bool Transcode::m_doTranscode( const QString &transStr )
95
{
Ludovic Fauvet's avatar
Ludovic Fauvet committed
96
    QString sout( ":sout=" );
97
98
    sout += transStr;

99
100
    char const *vlc_argv[] = 
    {
101
102
        "-I", "dummy", 
        "--no-skip-frame",
103
    };
104

105
106
107
    int vlc_argc = sizeof( vlc_argv ) / sizeof( *vlc_argv );

    libvlc_exception_init( &m_vlcEx );
108
    
109
110
    m_libvlc = libvlc_new( vlc_argc, vlc_argv, &m_vlcEx );
    if ( catchVLCException( &m_vlcEx ) )
111
112
        return false;
    
113
114
    m_vlcMedia = libvlc_media_new( m_libvlc, m_origVidPath.toLocal8Bit(), &m_vlcEx );
    if ( catchVLCException( &m_vlcEx ) ) 
115
116
117
118
119
120
        return false;

    libvlc_media_add_option(m_vlcMedia, sout.toStdString().c_str(), &m_vlcEx);
    if ( catchVLCException( &m_vlcEx ) ) 
        return false;

121
122
    m_vlcMp = libvlc_media_player_new_from_media( m_vlcMedia, &m_vlcEx );
    if ( catchVLCException( &m_vlcEx ) )
123
124
125
126
127
128
129
130
131
132
133
134
135
        return false;

    m_vlcEM = libvlc_media_player_event_manager( m_vlcMp, &m_vlcEx );
    if ( catchVLCException( &m_vlcEx ) ) 
        return false;

    libvlc_event_attach( m_vlcEM, libvlc_MediaPlayerPlaying, m_callback, this, &m_vlcEx );
    if ( catchVLCException( &m_vlcEx ) ) 
        return false;
    libvlc_event_attach( m_vlcEM, libvlc_MediaPlayerEndReached, m_callback, this,  &m_vlcEx );
    if ( catchVLCException( &m_vlcEx ) ) 
        return false;

136
137
    libvlc_media_player_play( m_vlcMp, &m_vlcEx );
    if ( catchVLCException( &m_vlcEx ) ) 
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
        return false;
    m_running = true;
    m_initProgressDialog();

    return true;
}

void Transcode::m_initProgressDialog()
{
    m_progress = new QProgressDialog( tr( "Transcode in progress" ), "Cancel", 0, 0);
    QObject::connect( m_progress, SIGNAL( canceled() ),
                      this, SLOT( cancelTranscode() ) );
    m_timer = new QTimer( this );
    QObject::connect( m_timer, SIGNAL( timeout() ),
                      this, SLOT( calcTranscodePercentage() ) );
    m_timer->start( 500 );
}

void Transcode::m_releaseVLCRessources()
{
    libvlc_media_release( m_vlcMedia );
    libvlc_media_player_release( m_vlcMp );
    libvlc_release( m_libvlc ); 
}

void Transcode::m_callback(const libvlc_event_t *event, void *ptr)
{
Ludovic Fauvet's avatar
Ludovic Fauvet committed
165
166
    Transcode* self = reinterpret_cast<Transcode*>( ptr );
    switch ( event->type )
167
168
169
170
171
172
173
    {
    case libvlc_MediaPlayerEndReached:
        self->m_running = false;
        break;
    default:
        break;
    }
174
175
}

176
177
void Transcode::on_dialogButtonBox_accepted()
{
178
    if ( m_origVidPath == "" )
179
180
181
182
183
184
    {
        QMessageBox::warning( this,
                              tr( "Warning" ),
                              tr( "Choose a video to transcode" ) );
        return ;
    }
185
    QString path = QFileDialog::getSaveFileName( this,
186
187
188
                                                 tr( "Choose File to save" ),
                                                 m_origVidPath,
                                                 tr( "Video files (*.avi *.mkv *.ogg)" ) );
189
    if ( path == "" )
190
        return ;
191
192
193
    QString type;
    QString transCodeString = "";

194
    //TODO : Use a file or a qsettings, coz this is fugly
195
    type = m_ui.profileSelector->itemData( m_ui.profileSelector->currentIndex() ).toString();
196
    if ( type ==  "h264" )
197
    {
198
199
200
201
202
203
204
        transCodeString = "#transcode{vcodec=h264,vb=800,scale=1,"
                          "fps=0,width=0,height=0,acodec=mp3,ab=128,"
                          "channels=2,samplerate=44100}:duplicate{dst=std{access=file,mux=ts,dst=\"";
    }
    else if ( type ==  "mp4" )
    {
        transCodeString = "#transcode{vcodec=mp4v,vb=800,scale=1,"
205
                          "fps=0,width=0,height=0,acodec=mp4a,ab=128,"
206
                          "channels=2,samplerate=44100}:duplicate{dst={std{access=file,mux=mp4,dst=\"";
207
    }
208
    else if ( type == "dirac" )
209
    {
210
        transCodeString = "#transcode{vcodec=drac,vb=800,scale=1,"
211
                          "fps=0,width=0,height=0,acodec=mp4a,ab=128,"
212
213
214
215
216
217
218
                          "channels=2,samplerate=44100}:duplicate{dst=std{access=file,mux=ts,dst=\"";
    }
    else if ( type == "thVorbis" )
    {
        transCodeString = "#transcode{vcodec=theo,vb=800,scale=1,"
                          "fps=0,width=0,height=0,acodec=vorb,ab=128,"
                          "channels=2,samplerate=44100}:duplicate{dst=std{access=file,mux=ogg,dst=\"";
219
    }
220
    else if ( type == "thFlac" )
221
    {
222
223
224
225
226
227
228
        transCodeString = "transcode{vcodec=theo,vb=800,scale=1,"
                          "fps=0,width=0,height=0,acodec=flac,ab=128,"
                          "channels=2,samplerate=44100}:duplicate{dst=std{access=file,mux=ogg,dst=\"";
    }   
    else if ( type == "wmv" ) 
    {
        transCodeString = "#transcode{vcodec=WMV2,vb=800,scale=1,"
229
                          "fps=0,width=0,height=0,acodec=wma,ab=128,"
230
                          "channels=2,samplerate=44100}:duplicate{dst=std{access=file,mux=asf,dst=\"";
231
232
    }
    transCodeString += path;
233
    transCodeString += "\"}}";
234

235
236
    if ( !m_doTranscode( transCodeString ) )
        return ;
237
238
239
240
241
242
243
244
245
246
    close();
}

void Transcode::on_dialogButtonBox_rejected()
{
    close();
}

void Transcode::on_addProfile_clicked()
{
247
    //TODO : show the profiles management widget;
248
249
250
251
}

void Transcode::on_editProfile_clicked()
{
252
    //TODO : show the profile management widget and load the selected profile
253
254
255
256
}

void Transcode::on_deleteProfile_clicked()
{
257
    //TODO : delete the selected profile
258
259
}

260
261
void Transcode::calcTranscodePercentage()
{
Ludovic Fauvet's avatar
Ludovic Fauvet committed
262
    m_progress->setValue( 10 );
263
264
265
266
267
268
    if ( !m_running )
    {
        m_timer->stop();
        m_releaseVLCRessources();
        delete m_progress;
        delete m_timer;
269
        m_running = false;
270
271
    }
}
272

273
274
275
void Transcode::cancelTranscode()
{
    m_timer->stop();
276
277
    libvlc_media_player_pause( m_vlcMp, &m_vlcEx );
    catchVLCException( &m_vlcEx );
278
279
280
    m_releaseVLCRessources();
    delete m_progress;
    delete m_timer;
281
    m_running = false;
282
}