sout.cpp 15.5 KB
Newer Older
zorglub's avatar
zorglub committed
1
/*****************************************************************************
2
 * sout.cpp : Stream output dialog ( old-style )
zorglub's avatar
zorglub committed
3
 ****************************************************************************
4
 * Copyright ( C ) 2006 the VideoLAN team
5
 * $Id$
zorglub's avatar
zorglub committed
6
7
8
9
10
11
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *
 * 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
12
 * ( at your option ) any later version.
zorglub's avatar
zorglub committed
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 *
 * 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.
 *****************************************************************************/

#include "dialogs/sout.hpp"
#include "qt4.hpp"
#include <vlc_streaming.h>

28
29
#include <iostream>
#include <QString>
zorglub's avatar
zorglub committed
30
31
#include <QFileDialog>

32
33
SoutDialog::SoutDialog( QWidget *parent, intf_thread_t *_p_intf,
                     bool _transcode_only ) : QVLCDialog( parent,  _p_intf )
zorglub's avatar
zorglub committed
34
{
35
    setWindowTitle( qtr( "Stream output" ) );
36

zorglub's avatar
zorglub committed
37
    /* UI stuff */
38
    ui.setupUi( this );
39

40
41
42
43
44
45
#define ADD_PROFILE( name ) ui.comboBox->addItem( name );
    ADD_PROFILE( "" )
    ADD_PROFILE( "Ipod" )
    ADD_PROFILE( "PSP" )
    ADD_PROFILE( "GSM" )
    ADD_PROFILE( "Custom" )
46

47
#define ADD_VCODEC( name, fourcc ) ui.vCodec_2->addItem( name, QVariant( fourcc ) );
48
49
50
51
52
53
54
55
56
57
58
59
60
    ADD_VCODEC( "MPEG-1", "mp1v" )
    ADD_VCODEC( "MPEG-2", "mp2v" )
    ADD_VCODEC( "MPEG-4", "mp4v" )
    ADD_VCODEC( "DIVX 1" , "DIV1" )
    ADD_VCODEC( "DIVX 2" , "DIV1" )
    ADD_VCODEC( "DIVX 3" , "DIV1" )
    ADD_VCODEC( "H-263", "H263" )
    ADD_VCODEC( "H-264", "h264" )
    ADD_VCODEC( "WMV1", "WMV1" )
    ADD_VCODEC( "WMV2" , "WMV2" )
    ADD_VCODEC( "M-JPEG", "MJPG" )
    ADD_VCODEC( "Theora", "theo" )

61
#define ADD_ACODEC( name, fourcc ) ui.aCodec_2->addItem( name, QVariant( fourcc ) );
62
63
    ADD_ACODEC( "MPEG Audio", "mpga" )
    ADD_ACODEC( "MP3", "mp3" )
64
65
    ADD_ACODEC( "MPEG 4 Audio ( AAC )", "mp4a" )
    ADD_ACODEC( "A52/AC-3", "a52" )
66
67
68
69
70
71
    ADD_ACODEC( "Vorbis", "vorb" )
    ADD_ACODEC( "Flac", "flac" )
    ADD_ACODEC( "Speex", "spx" )
    ADD_ACODEC( "WAV", "s16l" )
    ADD_ACODEC( "WMA", "wma" )

72
#define ADD_SCALING( factor ) ui.vScale_2->addItem( factor );
73
74
75
76
77
78
79
80
81
    ADD_SCALING( "0.25" )
    ADD_SCALING( "0.5" )
    ADD_SCALING( "0.75" )
    ADD_SCALING( "1" )
    ADD_SCALING( "1.25" )
    ADD_SCALING( "1.5" )
    ADD_SCALING( "1.75" )
    ADD_SCALING( "2" )

82
    ui.mrlEdit->setToolTip ( qtr( "Stream output string.\n This is automatically generated when you change the above settings,\n but you can update it manually." ) ) ;
83
84

//     /* Connect everything to the updateMRL function */
85
86
87
88
 #define CB( x ) CONNECT( ui.x, clicked( bool ), this, updateMRL() );
 #define CT( x ) CONNECT( ui.x, textChanged( const QString ), this, updateMRL() );
 #define CS( x ) CONNECT( ui.x, valueChanged( int ), this, updateMRL() );
 #define CC( x ) CONNECT( ui.x, currentIndexChanged( int ), this, updateMRL() );
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
//     /* Output */
     CB( fileOutput ); CB( HTTPOutput ); CB( localOutput );
     CB( UDPOutput ); CB( MMSHOutput ); CB( rawInput );
     CT( fileEdit ); CT( HTTPEdit ); CT( UDPEdit ); CT( MMSHEdit );
     CS( HTTPPort ); CS( UDPPort ); CS( MMSHPort );
//     /* Transcode */
     CC( vCodec_2 ); CC( sCodec_2 ); CC( aCodec_2 ) ;
     CB( transcodeVideo_2 ); CB( transcodeAudio_2 ); CB( transcodeSubs_2 );
//     CB( sOverlay );
     CS( vBitrate_2 ); CS( aBitrate_2 ); CS( aChannels_2 ); CC( vScale_2 );
//     /* Mux */
     CB( PSMux ); CB( TSMux ); CB( MPEG1Mux ); CB( OggMux ); CB( ASFMux );
     CB( MP4Mux ); CB( MOVMux ); CB( WAVMux ); CB( RAWMux ); CB( FLVMux );
//     /* Misc */
     CB( soutAll ); CS( ttl ); CT( sapName ); CT( sapGroup );
104
105
106
107
108
109
110
//
    connect( ui.comboBox, SIGNAL( activated( const QString & ) ), this, SLOT( setOptions() ) );
    connect( ui.fileSelectButton, SIGNAL( clicked() ), this, SLOT( fileBrowse() ) );
    connect( ui.transcodeVideo_2,SIGNAL( toggled( bool ) ),this,SLOT( setVTranscodeOptions( bool ) ) );
    connect( ui.transcodeAudio_2,SIGNAL( toggled( bool ) ),this,SLOT( setATranscodeOptions( bool ) ) );
    connect( ui.transcodeSubs_2,SIGNAL( toggled( bool ) ),this,SLOT( setSTranscodeOptions( bool ) ) );
    connect( ui.rawInput,SIGNAL( toggled( bool ) ),this,SLOT( setRawOptions( bool ) ) );
zorglub's avatar
zorglub committed
111

112
113
114
115
116
117
118
    QPushButton *okButton = new QPushButton( qtr( "&Stream" ) );
    QPushButton *cancelButton = new QPushButton( qtr( "&Cancel" ) );

    okButton->setDefault( true );
    ui.acceptButtonBox->addButton( okButton, QDialogButtonBox::AcceptRole );
    ui.acceptButtonBox->addButton( cancelButton, QDialogButtonBox::RejectRole );

119
120
    BUTTONACT( okButton, ok() );
    BUTTONACT( cancelButton, cancel() );
121
122

    if( _transcode_only ) toggleSout();
zorglub's avatar
zorglub committed
123
124
125
}

void SoutDialog::fileBrowse()
126
127
{ui.tabWidget->setTabEnabled( 0,false );
    QString f = QFileDialog::getOpenFileName( this, qtr( "Save file" ), "", "" );
zorglub's avatar
zorglub committed
128
129
130
131
    ui.fileEdit->setText( f );
    updateMRL();
}

132
void SoutDialog::setVTranscodeOptions( bool b_trans )
133
{
134
135
136
137
138
139
140
    ui.label_2->setEnabled( b_trans );
    ui.vCodec_2->setEnabled( b_trans );
    ui.vBitrateLabel_2->setEnabled( b_trans );
    ui.vScaleLabel_2->setEnabled( b_trans );
    ui.vBitrate_2->setEnabled( b_trans );
    ui.vScaleLabel_2->setEnabled( b_trans );
    ui.vScale_2->setEnabled( b_trans );
141
142
}

143
void SoutDialog::setATranscodeOptions( bool b_trans )
144
{
145
146
147
148
149
150
    ui.label->setEnabled( b_trans );
    ui.aCodec_2->setEnabled( b_trans );
    ui.aBitrateLabel_2->setEnabled( b_trans );
    ui.aBitrate_2->setEnabled( b_trans );
    ui.s_3->setEnabled( b_trans );
    ui.aChannels_2->setEnabled( b_trans );
151
152
}

153
void SoutDialog::setSTranscodeOptions( bool b_trans )
154
{
155
156
    ui.sCodec_2->setEnabled( b_trans );
    ui.sOverlay_2->setEnabled( b_trans );
157
158
}

159
void SoutDialog::setRawOptions( bool b_raw )
160
{
161
162
163
164
165
166
167
168
    if ( b_raw )
    {
        ui.tabWidget->setDisabled( true );
    }
    else
    {
        SoutDialog::setOptions();
    }
169
170
171
172
}

void SoutDialog::setOptions()
{
173
174
175
176
177
178
179
180
181
    /* The test is currently done with a QString, it could be done with the index, it'd depend how translation works */
    if ( ui.comboBox->currentText() == "Custom" )
    {
        ui.tabWidget->setEnabled( true );
    }
    else
    {
        ui.tabWidget->setDisabled( true );
    }
182
183
}

184
185
void SoutDialog::toggleSout()
{
186
187
#define TGV( x ) { \
     if( ( x->isHidden() ) )  \
188
189
190
191
192
193
194
195
        x->show();          \
     else  x->hide();\
}
 TGV( ui.HTTPOutput ) ; TGV( ui.UDPOutput ) ; TGV( ui.MMSHOutput ) ;
 TGV( ui.HTTPEdit ) ; TGV( ui.UDPEdit ) ; TGV( ui.MMSHEdit ) ;
 TGV( ui.HTTPLabel ) ; TGV( ui.UDPLabel ) ; TGV( ui.MMSHLabel ) ;
 TGV( ui.HTTPPortLabel ) ; TGV( ui.UDPPortLabel ) ; TGV( ui.MMSHPortLabel ) ;
 TGV( ui.HTTPPort ) ; TGV( ui.UDPPort ) ; TGV( ui.MMSHPort ) ;
196
 updateGeometry();
197
198
}

zorglub's avatar
zorglub committed
199
200
void SoutDialog::ok()
{
zorglub's avatar
zorglub committed
201
202
    mrl = ui.mrlEdit->text();
    accept();
zorglub's avatar
zorglub committed
203
204
205
}
void SoutDialog::cancel()
{
zorglub's avatar
zorglub committed
206
207
    mrl = ui.mrlEdit->text();
    reject();
zorglub's avatar
zorglub committed
208
209
210
211
}

void SoutDialog::updateMRL()
{
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
    sout_gui_descr_t sout;
    memset( &sout, 0, sizeof( sout_gui_descr_t ) );

    sout.b_local = ui.localOutput->isChecked();
    sout.b_file = ui.fileOutput->isChecked();
    sout.b_http = ui.HTTPOutput->isChecked();
    sout.b_mms = ui.MMSHOutput->isChecked();
    sout.b_udp = ui.UDPOutput->isChecked();
    sout.b_sap = ui.sap->isChecked();
    sout.b_all_es = ui.soutAll->isChecked();
    sout.psz_vcodec = strdup( qtu( ui.vCodec_2->itemData( ui.vCodec_2->currentIndex() ).toString() ) );
    sout.psz_acodec = strdup( qtu( ui.aCodec_2->itemData( ui.vCodec_2->currentIndex() ).toString() ) );
    sout.psz_scodec = strdup( qtu( ui.sCodec_2->itemData( ui.vCodec_2->currentIndex() ).toString() ) );
    sout.psz_file = strdup( qtu( ui.fileEdit->text() ) );
    sout.psz_http = strdup( qtu( ui.HTTPEdit->text() ) );
    sout.psz_mms = strdup( qtu( ui.MMSHEdit->text() ) );
    sout.psz_udp = strdup( qtu( ui.UDPEdit->text() ) );
    sout.i_http = ui.HTTPPort->value();
    sout.i_mms = ui.MMSHPort->value();
    sout.i_udp = ui.UDPPort->value();
    sout.i_ab = ui.aBitrate_2->value();
    sout.i_vb = ui.vBitrate_2->value();
    sout.i_channels = ui.aChannels_2->value();
    sout.f_scale = atof( qta( ui.vScale_2->currentText() ) );
    sout.psz_group = strdup( qtu( ui.sapGroup->text() ) );
    sout.psz_name = strdup( qtu( ui.sapName->text() ) );

#define SMUX( x, txt ) if( ui.x->isChecked() ) sout.psz_mux = strdup( txt );
        SMUX( PSMux, "ps" );
        SMUX( TSMux, "ts" );
        SMUX( MPEG1Mux, "mpeg" );
        SMUX( OggMux, "ogg" );
        SMUX( ASFMux, "asf" );
        SMUX( MP4Mux, "mp4" );
        SMUX( MOVMux, "mov" );
        SMUX( WAVMux, "wav" );
        SMUX( RAWMux, "raw" );
        SMUX( FLVMux, "flv" );

    bool trans = false;
    bool more = false;

if ( ui.transcodeVideo_2->isChecked() || ui.transcodeAudio_2->isChecked() )
255
{
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
     if ( ui.transcodeVideo_2->isChecked() )
     {
        mrl = ":sout=#transcode{";
         mrl.append( "vcodec=" );
        mrl.append( sout.psz_vcodec );
        mrl.append( "," );
        mrl.append( "vb=" );
        mrl.append( QString::number( sout.i_vb,10 ) );
        mrl.append( "," );
        mrl.append( "scale=" );
        mrl.append( QString::number( sout.f_scale ) );
        trans = true;
     }

    if ( ui.transcodeAudio_2->isChecked() )
    {
        if ( trans )
        {
            mrl.append( "," );
        }
        else
        {
            mrl = ":sout=#transcode{";
        }
        mrl.append( "acodec=" );
        mrl.append( sout.psz_acodec );
        mrl.append( "," );
        mrl.append( "ab=" );
        mrl.append( QString::number( sout.i_ab,10 ) );
        mrl.append( "," );
        mrl.append( "channels=" );
        mrl.append( QString::number( sout.i_channels,10 ) );
        trans = true;
    }
    mrl.append( "}" );
zorglub's avatar
zorglub committed
291
}
292

293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
    if ( sout.b_local || sout.b_file || sout.b_http || sout.b_mms || sout.b_udp )
    {

#define ISMORE() if ( more ) mrl.append( "," );

        if ( trans )
        {
            mrl.append( ":duplicate{" );
        }
        else
        {
            mrl = ":sout=#";
        }

        if ( sout.b_local )
        {
            ISMORE();
            mrl.append( "dst=display" );
            more = true;
        }

        if ( sout.b_file )
        {
            ISMORE();
            mrl.append( "dst=std{access=file,mux=" );
            mrl.append( sout.psz_mux );
            mrl.append( ",dst=" );
            mrl.append( sout.psz_file );
            mrl.append( "}" );
            more = true;
        }

        if ( sout.b_http )
        {
            ISMORE();
            mrl.append( "dst=std{access=http,mux=" );
            mrl.append( sout.psz_mux );
            mrl.append( ",dst=" );
            mrl.append( sout.psz_http );
            mrl.append( ":" );
            mrl.append( QString::number( sout.i_http,10 ) );
            mrl.append( "}" );
            more = true;
        }

        if ( sout.b_mms )
        {
            ISMORE();
            mrl.append( "dst=std{access=mmsh,mux=" );
            mrl.append( sout.psz_mux );
            mrl.append( ",dst=" );
            mrl.append( sout.psz_mms );
            mrl.append( ":" );
            mrl.append( QString::number( sout.i_mms,10 ) );
            mrl.append( "}" );
            more = true;
        }

        if ( sout.b_udp )
        {
            ISMORE();
            mrl.append( "dst=std{access=udp,mux=" );
            mrl.append( sout.psz_mux );
            mrl.append( ",dst=" );
            mrl.append( sout.psz_udp );
            mrl.append( ":" );
            mrl.append( QString::number( sout.i_udp,10 ) );
            if ( sout.b_sap )
            {
                mrl.append( ",sap," );
                mrl.append( "group=\"" );
                mrl.append( sout.psz_group );
                mrl.append( "\"," );
                mrl.append( "name=\"" );
                mrl.append( sout.psz_name );
                mrl.append( "\"" );
            }
            mrl.append( "}" );
            more = true;
        }

        if ( trans )
        {
            mrl.append( "}" );
        }
    }

    if ( sout.b_all_es )
            mrl.append( ":sout-all" );


    ui.mrlEdit->setText( mrl );
    free( sout.psz_acodec ); free( sout.psz_vcodec ); free( sout.psz_scodec );
    free( sout.psz_file );free( sout.psz_http ); free( sout.psz_mms );
    free( sout.psz_udp ); free( sout.psz_mux );
    free( sout.psz_name ); free( sout.psz_group );
389
390
391
392
393
394
}

// void SoutDialog::updateMRL()
// {
//     sout_gui_descr_t pd;
//     memset( &pd, 0, sizeof( sout_gui_descr_t ) );
395
//
396
397
398
//     /* Output */
//     pd.b_dump = ui.rawInput->isChecked();
//     if( pd.b_dump ) goto end;
399
//
400
401
402
403
404
//     pd.b_local = ui.localOutput->isChecked();
//     pd.b_file = ui.fileOutput->isChecked();
//     pd.b_http = ui.HTTPOutput->isChecked();
//     pd.b_mms = ui.MMSHOutput->isChecked();
//     pd.b_udp = ui.UDPOutput->isChecked();
405
//
406
//     pd.psz_file = ui.fileOutput->isChecked() ?
407
//                             strdup( qtu( ui.fileEdit->text() ) ): NULL;
408
//     pd.psz_http = ui.HTTPOutput->isChecked() ?
409
//                             strdup( qtu( ui.HTTPEdit->text() ) ) : NULL;
410
//     pd.psz_mms = ui.MMSHOutput->isChecked() ?
411
//                             strdup( qtu( ui.MMSHEdit->text() ) ): NULL;
412
413
//     pd.psz_udp = ui.UDPOutput->isChecked() ?
//                             strdup( qtu( ui.UDPEdit->text() ) ): NULL;
414
//
415
416
417
//     pd.i_http = ui.HTTPPort->value();
//     pd.i_mms = ui.MMSHPort->value();
//     pd.i_udp = ui.UDPPort->value();
418
//
419
//     /* Mux */
420
// #define SMUX( x, txt ) if( ui.x##Mux->isChecked() ) pd.psz_mux = strdup( txt );
421
422
423
424
425
426
427
428
429
430
//     SMUX( PS, "ps" );
//     SMUX( TS, "ts" );
//     SMUX( MPEG1, "mpeg" );
//     SMUX( Ogg, "ogg" );
//     SMUX( ASF, "asf" );
//     SMUX( MP4, "mp4" );
//     SMUX( MOV, "mov" );
//     SMUX( WAV, "wav" );
//     SMUX( RAW, "raw" );
//     SMUX( FLV, "flv" );
431
432
433
//
//
//
434
435
436
437
438
439
//     /* Transcode */
// //     pd.b_soverlay = ui.sOverlay->isChecked();
// //     pd.i_vb = ui.vBitrate->value();
// //     pd.i_ab = ui.aBitrate->value();
// //     pd.i_channels = ui.aChannels->value();
// //     pd.f_scale = atof( qta( ui.vScale->currentText() ) );
440
// //
441
// //     pd.psz_vcodec = ui.transcodeVideo->isChecked() ?
442
// //                      strdup( qtu( ui.vCodec->itemData( 
443
444
// //                             ui.vCodec->currentIndex() ). toString() ) ) : NULL;
// //     pd.psz_acodec = ui.transcodeAudio->isChecked() ?
445
// //                      strdup( qtu( ui.aCodec->itemData( 
446
447
// //                             ui.aCodec->currentIndex() ).toString() ) ) : NULL;
// //     pd.psz_scodec = ui.transcodeSubs->isChecked() ?
448
// //                      strdup( qtu( ui.sCodec->itemData( 
449
450
451
452
453
454
455
456
// //                             ui.sCodec->currentIndex() ).toString() ) ) : NULL;
// //     pd.b_sap = ui.sap->isChecked();
// //     pd.b_all_es = ui.soutAll->isChecked();
// //     pd.psz_name = qtu( ui.sapName->text() );
// //     pd.psz_group = qtu( ui.sapGroup->text() );
// //     pd.i_ttl = ui.ttl->value() ;
// end:
//     sout_chain_t* p_chain = streaming_ChainNew();
457
//     streaming_GuiDescToChain( VLC_OBJECT( p_intf ), p_chain, &pd );
458
//     char *psz_mrl = streaming_ChainToPsz( p_chain );
459
460
//
//     ui.mrlEdit->setText( qfu( strdup( psz_mrl ) ) );
461
462
463
464
//     free( pd.psz_acodec ); free( pd.psz_vcodec ); free( pd.psz_scodec );
//     free( pd.psz_file );free( pd.psz_http ); free( pd.psz_mms );
//     free( pd.psz_udp ); free( pd.psz_mux );
// }