~ubuntu-branches/ubuntu/trusty/k3b/trusty

« back to all changes in this revision

Viewing changes to .pc/ffmpeg-more.diff/plugins/decoder/ffmpeg/k3bffmpegwrapper.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-11-12 10:36:01 UTC
  • mfrom: (2.1.20 sid)
  • Revision ID: package-import@ubuntu.com-20131112103601-q6vvln9lv3mg7qxh
Tags: 2.0.2-7ubuntu1
* Merge with Debian, remaining changes:
  - Suggest, not recommend libk3b6-extracodecs (Cannot be on the CD)
  - Do not ship k3b documentation, it's for the KDE3 version.
  - Do not install unused scalable icons to save space
  - Keep kubuntu_02_kubuntu_restricted.diff
  - Keep kubuntu_03_no_missing_mp3_warn.diff
  - Keep kubuntu_05_no_system_settings.diff
  - Keep kubuntu_07_quicklists.diff
  - Disable 111_advice_debian_libk3b3-extracodes.diff and
    112_dont_require_mp3.diff which aren't required due to our mp3 patches.
  - swap kubuntu_06_libav_0.7.diff for Debian's
    Fixed_compilation_with_new_FFMPEG.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 *
 
4
 * Copyright (C) 2004-2008 Sebastian Trueg <trueg@k3b.org>
 
5
 *
 
6
 * This file is part of the K3b project.
 
7
 * Copyright (C) 1998-2008 Sebastian Trueg <trueg@k3b.org>
 
8
 *
 
9
 * This program is free software; you can redistribute it and/or modify
 
10
 * it under the terms of the GNU General Public License as published by
 
11
 * the Free Software Foundation; either version 2 of the License, or
 
12
 * (at your option) any later version.
 
13
 * See the file "COPYING" for the exact licensing terms.
 
14
 */
 
15
#include "k3bffmpegwrapper.h"
 
16
 
 
17
#include <config-k3b.h>
 
18
 
 
19
extern "C" {
 
20
/*
 
21
 Recent versions of FFmepg uses C99 constant macros which are not presebt in C++ standard.
 
22
 The macro __STDC_CONSTANT_MACROS allow C++ to use these macros. Altough it's not defined by C++ standard
 
23
 it's supported by many implementations.
 
24
 See bug 236036 and discussion: http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2010-May/088074.html
 
25
 */
 
26
#define __STDC_CONSTANT_MACROS
 
27
#ifdef NEWFFMPEGAVCODECPATH
 
28
#include <libavcodec/avcodec.h>
 
29
#include <libavformat/avformat.h>
 
30
#else
 
31
#include <ffmpeg/avcodec.h>
 
32
#include <ffmpeg/avformat.h>
 
33
#endif
 
34
}
 
35
 
 
36
#include <string.h>
 
37
 
 
38
#include <klocale.h>
 
39
 
 
40
 
 
41
#if LIBAVFORMAT_BUILD < 4629
 
42
#define FFMPEG_BUILD_PRE_4629
 
43
#endif
 
44
 
 
45
 
 
46
K3bFFMpegWrapper* K3bFFMpegWrapper::s_instance = 0;
 
47
 
 
48
 
 
49
class K3bFFMpegFile::Private
 
50
{
 
51
public:
 
52
    ::AVFormatContext* formatContext;
 
53
    ::AVCodec* codec;
 
54
 
 
55
    K3b::Msf length;
 
56
 
 
57
    // for decoding. ffmpeg requires 16-byte alignment.
 
58
    char outputBuffer[AVCODEC_MAX_AUDIO_FRAME_SIZE + 15];
 
59
    char* alignedOutputBuffer;
 
60
    char* outputBufferPos;
 
61
    int outputBufferSize;
 
62
    ::AVPacket packet;
 
63
    quint8* packetData;
 
64
    int packetSize;
 
65
};
 
66
 
 
67
 
 
68
K3bFFMpegFile::K3bFFMpegFile( const QString& filename )
 
69
    : m_filename(filename)
 
70
{
 
71
    d = new Private;
 
72
    d->formatContext = 0;
 
73
    d->codec = 0;
 
74
    int offset = 0x10 - (reinterpret_cast<intptr_t>(&d->outputBuffer) & 0xf);
 
75
    d->alignedOutputBuffer = &d->outputBuffer[offset];
 
76
}
 
77
 
 
78
 
 
79
K3bFFMpegFile::~K3bFFMpegFile()
 
80
{
 
81
    close();
 
82
    delete d;
 
83
}
 
84
 
 
85
 
 
86
bool K3bFFMpegFile::open()
 
87
{
 
88
    close();
 
89
 
 
90
    // open the file
 
91
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,2,0)
 
92
    int err = ::avformat_open_input( &d->formatContext, m_filename.toLocal8Bit(), 0, 0 );
 
93
#else
 
94
    int err = ::av_open_input_file( &d->formatContext, m_filename.toLocal8Bit(), 0, 0, 0 );
 
95
#endif
 
96
    if( err < 0 ) {
 
97
        kDebug() << "(K3bFFMpegFile) unable to open " << m_filename << " with error " << err;
 
98
        return false;
 
99
    }
 
100
 
 
101
    // analyze the streams
 
102
    ::av_find_stream_info( d->formatContext );
 
103
 
 
104
    // we only handle files containing one audio stream
 
105
    if( d->formatContext->nb_streams != 1 ) {
 
106
        kDebug() << "(K3bFFMpegFile) more than one stream in " << m_filename;
 
107
        return false;
 
108
    }
 
109
 
 
110
    // urgh... ugly
 
111
#ifdef FFMPEG_BUILD_PRE_4629
 
112
    ::AVCodecContext* codecContext =  &d->formatContext->streams[0]->codec;
 
113
#else
 
114
    ::AVCodecContext* codecContext =  d->formatContext->streams[0]->codec;
 
115
#endif
 
116
    if( codecContext->codec_type != 
 
117
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 64, 0)
 
118
        AVMEDIA_TYPE_AUDIO)
 
119
#else
 
120
        CODEC_TYPE_AUDIO)
 
121
#endif
 
122
    {
 
123
        kDebug() << "(K3bFFMpegFile) not a simple audio stream: " << m_filename;
 
124
        return false;
 
125
    }
 
126
 
 
127
    // get the codec
 
128
    d->codec = ::avcodec_find_decoder(codecContext->codec_id);
 
129
    if( !d->codec ) {
 
130
        kDebug() << "(K3bFFMpegFile) no codec found for " << m_filename;
 
131
        return false;
 
132
    }
 
133
 
 
134
    // open the codec on our context
 
135
    kDebug() << "(K3bFFMpegFile) found codec for " << m_filename;
 
136
    if( ::avcodec_open( codecContext, d->codec ) < 0 ) {
 
137
        kDebug() << "(K3bFFMpegDecoderFactory) could not open codec.";
 
138
        return false;
 
139
    }
 
140
 
 
141
    // determine the length of the stream
 
142
    d->length = K3b::Msf::fromSeconds( (double)d->formatContext->duration / (double)AV_TIME_BASE );
 
143
 
 
144
    if( d->length == 0 ) {
 
145
        kDebug() << "(K3bFFMpegDecoderFactory) invalid length.";
 
146
        return false;
 
147
    }
 
148
 
 
149
    // dump some debugging info
 
150
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,2,0)
 
151
    ::av_dump_format( d->formatContext, 0, m_filename.toLocal8Bit(), 0 );
 
152
#else
 
153
    ::dump_format( d->formatContext, 0, m_filename.toLocal8Bit(), 0 );
 
154
#endif
 
155
 
 
156
    return true;
 
157
}
 
158
 
 
159
 
 
160
void K3bFFMpegFile::close()
 
161
{
 
162
    d->outputBufferSize = 0;
 
163
    d->packetSize = 0;
 
164
    d->packetData = 0;
 
165
 
 
166
    if( d->codec ) {
 
167
#ifdef FFMPEG_BUILD_PRE_4629
 
168
        ::avcodec_close( &d->formatContext->streams[0]->codec );
 
169
#else
 
170
        ::avcodec_close( d->formatContext->streams[0]->codec );
 
171
#endif
 
172
        d->codec = 0;
 
173
    }
 
174
 
 
175
    if( d->formatContext ) {
 
176
        ::av_close_input_file( d->formatContext );
 
177
        d->formatContext = 0;
 
178
    }
 
179
}
 
180
 
 
181
 
 
182
K3b::Msf K3bFFMpegFile::length() const
 
183
{
 
184
    return d->length;
 
185
}
 
186
 
 
187
 
 
188
int K3bFFMpegFile::sampleRate() const
 
189
{
 
190
#ifdef FFMPEG_BUILD_PRE_4629
 
191
    return d->formatContext->streams[0]->codec.sample_rate;
 
192
#else
 
193
    return d->formatContext->streams[0]->codec->sample_rate;
 
194
#endif
 
195
}
 
196
 
 
197
 
 
198
int K3bFFMpegFile::channels() const
 
199
{
 
200
#ifdef FFMPEG_BUILD_PRE_4629
 
201
    return d->formatContext->streams[0]->codec.channels;
 
202
#else
 
203
    return d->formatContext->streams[0]->codec->channels;
 
204
#endif
 
205
}
 
206
 
 
207
 
 
208
int K3bFFMpegFile::type() const
 
209
{
 
210
#ifdef FFMPEG_BUILD_PRE_4629
 
211
    return d->formatContext->streams[0]->codec.codec_id;
 
212
#else
 
213
    return d->formatContext->streams[0]->codec->codec_id;
 
214
#endif
 
215
}
 
216
 
 
217
 
 
218
QString K3bFFMpegFile::typeComment() const
 
219
{
 
220
    switch( type() ) {
 
221
    case CODEC_ID_WMAV1:
 
222
        return i18n("Windows Media v1");
 
223
    case CODEC_ID_WMAV2:
 
224
        return i18n("Windows Media v2");
 
225
#if LIBAVCODEC_VERSION_MAJOR < 52
 
226
    case CODEC_ID_MP3LAME:
 
227
#else
 
228
    case CODEC_ID_MP3:
 
229
#endif
 
230
        return i18n("MPEG 1 Layer III");
 
231
    case CODEC_ID_AAC:
 
232
        return i18n("Advanced Audio Coding (AAC)");
 
233
    default:
 
234
        return QString::fromLocal8Bit( d->codec->name );
 
235
    }
 
236
}
 
237
 
 
238
 
 
239
QString K3bFFMpegFile::title() const
 
240
{
 
241
    // FIXME: is this UTF8 or something??
 
242
    AVDictionaryEntry *ade = av_dict_get( d->formatContext->metadata, "TITLE", NULL, 0 );
 
243
    if( ade == NULL )
 
244
        return QString();
 
245
    if( ade->value != '\0' )
 
246
        return QString::fromLocal8Bit( ade->value );
 
247
    else
 
248
        return QString();
 
249
}
 
250
 
 
251
 
 
252
QString K3bFFMpegFile::author() const
 
253
{
 
254
    // FIXME: is this UTF8 or something??
 
255
    AVDictionaryEntry *ade = av_dict_get( d->formatContext->metadata, "ARTIST", NULL, 0 );
 
256
    if( ade == NULL )
 
257
        return QString();
 
258
    if( ade->value != '\0' )
 
259
        return QString::fromLocal8Bit( ade->value );
 
260
    else
 
261
        return QString();
 
262
}
 
263
 
 
264
 
 
265
QString K3bFFMpegFile::comment() const
 
266
{
 
267
    // FIXME: is this UTF8 or something??
 
268
    AVDictionaryEntry *ade = av_dict_get( d->formatContext->metadata, "COMMENT", NULL, 0 );
 
269
    if( ade == NULL )
 
270
        return QString();
 
271
    if( ade->value != '\0' )
 
272
        return QString::fromLocal8Bit( ade->value );
 
273
    else
 
274
        return QString();
 
275
}
 
276
 
 
277
 
 
278
int K3bFFMpegFile::read( char* buf, int bufLen )
 
279
{
 
280
    int ret = fillOutputBuffer();
 
281
    if (ret <= 0) {
 
282
        return ret;
 
283
    }
 
284
 
 
285
    int len = qMin(bufLen, d->outputBufferSize);
 
286
    ::memcpy( buf, d->outputBufferPos, len );
 
287
 
 
288
    // TODO: only swap if needed
 
289
    for( int i = 0; i < len-1; i+=2 ) {
 
290
        char a = buf[i];
 
291
        buf[i] = buf[i+1];
 
292
        buf[i+1] = a;
 
293
    }
 
294
 
 
295
    d->outputBufferPos += len;
 
296
    d->outputBufferSize -= len;
 
297
    return len;
 
298
}
 
299
 
 
300
 
 
301
// fill d->packetData with data to decode
 
302
int K3bFFMpegFile::readPacket()
 
303
{
 
304
    if( d->packetSize <= 0 ) {
 
305
        ::av_init_packet( &d->packet );
 
306
 
 
307
        if( ::av_read_frame( d->formatContext, &d->packet ) < 0 ) {
 
308
            return 0;
 
309
        }
 
310
        d->packetSize = d->packet.size;
 
311
        d->packetData = d->packet.data;
 
312
    }
 
313
 
 
314
    return d->packetSize;
 
315
}
 
316
 
 
317
 
 
318
// decode data in d->packetData and fill d->outputBuffer
 
319
int K3bFFMpegFile::fillOutputBuffer()
 
320
{
 
321
    // decode if the output buffer is empty
 
322
    if( d->outputBufferSize <= 0 ) {
 
323
 
 
324
        // make sure we have data to decode
 
325
        if( readPacket() == 0 ) {
 
326
            return 0;
 
327
        }
 
328
 
 
329
        d->outputBufferPos = d->alignedOutputBuffer;
 
330
        d->outputBufferSize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
 
331
 
 
332
#if LIBAVCODEC_VERSION_MAJOR < 52
 
333
        int len = ::avcodec_decode_audio(
 
334
#else
 
335
   #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 64, 0)
 
336
        int len = ::avcodec_decode_audio3(
 
337
   #else
 
338
        int len = ::avcodec_decode_audio2(
 
339
   #endif
 
340
#endif
 
341
 
 
342
#ifdef FFMPEG_BUILD_PRE_4629
 
343
            &d->formatContext->streams[0]->codec,
 
344
#else
 
345
            d->formatContext->streams[0]->codec,
 
346
#endif
 
347
            (short*)d->alignedOutputBuffer,
 
348
            &d->outputBufferSize,
 
349
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 64, 0)
 
350
            &d->packet );
 
351
#else
 
352
            d->packetData, d->packetSize );
 
353
#endif
 
354
 
 
355
        if( d->packetSize <= 0 || len < 0 )
 
356
            ::av_free_packet( &d->packet );
 
357
        if( len < 0 ) {
 
358
            kDebug() << "(K3bFFMpegFile) decoding failed for " << m_filename;
 
359
            return -1;
 
360
        }
 
361
 
 
362
        d->packetSize -= len;
 
363
        d->packetData += len;
 
364
    }
 
365
 
 
366
    // if it is still empty try again
 
367
    if( d->outputBufferSize <= 0 )
 
368
        return fillOutputBuffer();
 
369
    else
 
370
        return d->outputBufferSize;
 
371
}
 
372
 
 
373
 
 
374
bool K3bFFMpegFile::seek( const K3b::Msf& msf )
 
375
{
 
376
    d->outputBufferSize = 0;
 
377
    d->packetSize = 0;
 
378
 
 
379
    double seconds = (double)msf.totalFrames()/75.0;
 
380
    quint64 timestamp = (quint64)(seconds * (double)AV_TIME_BASE);
 
381
 
 
382
    // FIXME: do we really need the start_time and why?
 
383
#if LIBAVFORMAT_BUILD >= 4619
 
384
    return ( ::av_seek_frame( d->formatContext, -1, timestamp + d->formatContext->start_time, 0 ) >= 0 );
 
385
#else
 
386
    return ( ::av_seek_frame( d->formatContext, -1, timestamp + d->formatContext->start_time ) >= 0 );
 
387
#endif
 
388
}
 
389
 
 
390
 
 
391
 
 
392
 
 
393
 
 
394
 
 
395
K3bFFMpegWrapper::K3bFFMpegWrapper()
 
396
{
 
397
    ::av_register_all();
 
398
}
 
399
 
 
400
 
 
401
K3bFFMpegWrapper::~K3bFFMpegWrapper()
 
402
{
 
403
    s_instance = 0;
 
404
}
 
405
 
 
406
 
 
407
K3bFFMpegWrapper* K3bFFMpegWrapper::instance()
 
408
{
 
409
    if( !s_instance ) {
 
410
        s_instance = new K3bFFMpegWrapper();
 
411
    }
 
412
 
 
413
    return s_instance;
 
414
}
 
415
 
 
416
 
 
417
K3bFFMpegFile* K3bFFMpegWrapper::open( const QString& filename ) const
 
418
{
 
419
    K3bFFMpegFile* file = new K3bFFMpegFile( filename );
 
420
    if( file->open() ) {
 
421
#ifndef K3B_FFMPEG_ALL_CODECS
 
422
        //
 
423
        // only allow tested formats. ffmpeg seems not to be too reliable with every format.
 
424
        // mp3 being one of them sadly. Most importantly: allow the libsndfile decoder to do
 
425
        // its thing.
 
426
        //
 
427
        if( file->type() == CODEC_ID_WMAV1 ||
 
428
            file->type() == CODEC_ID_WMAV2 ||
 
429
            file->type() == CODEC_ID_AAC )
 
430
#endif
 
431
            return file;
 
432
    }
 
433
 
 
434
    delete file;
 
435
    return 0;
 
436
}