[haiku-commits] haiku: hrev49933 - src/add-ons/media/plugins/ffmpeg

  • From: pulkomandy@xxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 19 Dec 2015 21:58:38 +0100 (CET)

hrev49933 adds 1 changeset to branch 'master'
old head: 92734afaa2ff579ae4630d58dd50017e067eaa9b
new head: 9dd9b4543645aaf7b5b5b7acddef048c7214375b
overview:
http://cgit.haiku-os.org/haiku/log/?qt=range&q=9dd9b4543645+%5E92734afaa2ff

----------------------------------------------------------------------------

9dd9b4543645: Use swresample to rematrix audio channels, try 2

This code is closer to what we used before for gcc2, and should not
crash there anymore. I could not get exactly the same code to work, but
reduced the difference to a single statement (which makes gcc2 work and
breaks gcc4). This is protected under a guard with appropriate ffmpeg
version test.

This code works for both gcc2 and gcc4 (tested with mp3 and aac files as
well as youtube videos). It still gets the timestamps wrong with ffmpeg
2.4, but I'll try to solve that another time.

[ Adrien Destugues <pulkomandy@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision: hrev49933
Commit: 9dd9b4543645aaf7b5b5b7acddef048c7214375b
URL: http://cgit.haiku-os.org/haiku/commit/?id=9dd9b4543645
Author: Adrien Destugues <pulkomandy@xxxxxxxxx>
Date: Sat Dec 19 17:41:34 2015 UTC

----------------------------------------------------------------------------

3 files changed, 61 insertions(+), 26 deletions(-)
.../media/plugins/ffmpeg/AVCodecDecoder.cpp | 78 +++++++++++++-------
.../media/plugins/ffmpeg/AVCodecDecoder.h | 8 ++
src/add-ons/media/plugins/ffmpeg/Jamfile | 1 +

----------------------------------------------------------------------------

diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
index c1c2bb4..d4b3173 100644
--- a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
+++ b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
@@ -5,12 +5,14 @@
* Copyright (C) 2004 Marcus Overhagen
* Copyright (C) 2009 Stephan Amßus <superstippi@xxxxxx>
* Copyright (C) 2014 Colin Günther <coling@xxxxxx>
+ * Copyright (C) 2015 Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
*
* All rights reserved. Distributed under the terms of the MIT License.
*/

//! libavcodec based decoder for Haiku

+
#include "AVCodecDecoder.h"

#include <new>
@@ -87,6 +89,7 @@ AVCodecDecoder::AVCodecDecoder()
fIsAudio(false),
fCodec(NULL),
fContext(avcodec_alloc_context3(NULL)),
+ fResampleContext(NULL),
fDecodedData(NULL),
fDecodedDataSizeInBytes(0),
fPostProcessedDecodedPicture(avcodec_alloc_frame()),
@@ -144,6 +147,7 @@ AVCodecDecoder::~AVCodecDecoder()
if (fCodecInitDone)
avcodec_close(fContext);

+ swr_free(&fResampleContext);
free(fChunkBuffer);
free(fDecodedData);

@@ -229,8 +233,7 @@ AVCodecDecoder::Setup(media_format* ioEncodedFormat, const
void* infoBuffer,
} else {
if (fIsAudio) {
fBlockAlign
- =
ioEncodedFormat->u.encoded_audio.output
- .buffer_size;
+ =
ioEncodedFormat->u.encoded_audio.output.buffer_size;
TRACE(" using buffer_size as block align:
%d\n",
fBlockAlign);
}
@@ -405,6 +408,13 @@ AVCodecDecoder::_NegotiateAudioOutputFormat(media_format*
inOutFormat)
if (fRawDecodedAudio->opaque == NULL)
return B_NO_MEMORY;

+ fResampleContext = swr_alloc_set_opts(NULL,
+ fContext->channel_layout, fContext->request_sample_fmt,
+ fContext->sample_rate,
+ fContext->channel_layout, fContext->sample_fmt,
fContext->sample_rate,
+ 0, NULL);
+ swr_init(fResampleContext);
+
TRACE(" bit_rate = %d, sample_rate = %d, channels = %d, "
"output frame size: %d, count: %ld, rate: %.2f\n",
fContext->bit_rate, fContext->sample_rate, fContext->channels,
@@ -894,24 +904,42 @@
AVCodecDecoder::_MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes()
assert(fRawDecodedAudio->nb_samples < fOutputFrameCount);
assert(fOutputFrameRate > 0);

- int32 frames = min_c(fOutputFrameCount - fRawDecodedAudio->nb_samples,
- fDecodedDataBufferSize / fOutputFrameSize);
+ int32 outFrames = fOutputFrameCount - fRawDecodedAudio->nb_samples;
+ int32 inFrames = fDecodedDataBufferSize;
+
+ int32 frames = min_c(outFrames, inFrames);
if (frames == 0)
debugger("fDecodedDataBufferSize not multiple of frame size!");

- size_t remainingSize = frames * fOutputFrameSize;
+ // The old version of libswresample available for gcc2 gets confused
when
+ // the frame counts for inout and output don't match. So, we use it with
+ // equal frame counts (but it can still perform re-matrixing of the
audio).
+#if LIBSWRESAMPLE_VERSION_INT <= AV_VERSION_INT(0, 6, 100)
+ //outFrames = frames;
+ inFrames = frames;
+#endif

-#if 0
// Some decoders do not support format conversion on themselves, or use
// "planar" audio (each channel separated instead of interleaved
samples).
- // If this is a problem we will need to use swresample to convert the
data
- // here, instead of directly copying it.
- swr_convert(fResampleContext, fRawDecodedAudio->data,
- fDecodedDataBuffer->data + fDecodedDataBufferOffset, frames);
-#else
- memcpy(fRawDecodedAudio->data[0], fDecodedDataBuffer->data[0]
- + fDecodedDataBufferOffset, remainingSize);
-#endif
+ // In that case, we use swresample to convert the data (and it is
+ // smart enough to do just a copy, when possible)
+ const uint8_t* ptr[8];
+ for (int i = 0; i < 8; i++) {
+ if (fDecodedDataBuffer->data[i] == NULL)
+ ptr[i] = NULL;
+ else
+ ptr[i] = fDecodedDataBuffer->data[i] +
fDecodedDataBufferOffset;
+ }
+
+ int32 result = swr_convert(fResampleContext, fRawDecodedAudio->data,
+ outFrames, ptr, inFrames);
+
+ size_t remainingSize = inFrames * fOutputFrameSize;
+ size_t decodedSize = outFrames * fOutputFrameSize;
+ fDecodedDataBufferSize -= inFrames;
+
+ if (result < 0)
+ debugger("resampling failed");

bool firstAudioFramesCopiedToRawDecodedAudio
= fRawDecodedAudio->data[0] != fDecodedData;
@@ -925,22 +953,21 @@
AVCodecDecoder::_MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes()
codecContext->sample_rate = fContext->sample_rate;
}

- fRawDecodedAudio->data[0] += remainingSize;
- fRawDecodedAudio->linesize[0] += remainingSize;
- fRawDecodedAudio->nb_samples += frames;
+ fRawDecodedAudio->data[0] += decodedSize;
+ fRawDecodedAudio->linesize[0] += decodedSize;
+ fRawDecodedAudio->nb_samples += outFrames;

fDecodedDataBufferOffset += remainingSize;
- fDecodedDataBufferSize -= remainingSize;

// Update start times accordingly
bigtime_t framesTimeInterval = static_cast<bigtime_t>(
(1000000LL * frames) / fOutputFrameRate);
fDecodedDataBuffer->pkt_dts += framesTimeInterval;
- // Start time of buffer is updated in case that it contains
- // more audio frames to move.
+ // Start time of buffer is updated in case that it contains
+ // more audio frames to move.
fTempPacket.dts += framesTimeInterval;
- // Start time of fTempPacket is updated in case the fTempPacket
- // contains more audio frames to decode.
+ // Start time of fTempPacket is updated in case the fTempPacket
+ // contains more audio frames to decode.
}


@@ -965,6 +992,7 @@
AVCodecDecoder::_MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes()
2. fDecodedDataBufferOffset is set to zero.
3. fDecodedDataBuffer contains audio frames.

+
\returns B_OK on successfully decoding one audio frame chunk.
\returns B_LAST_BUFFER_ERROR No more audio frame chunks available. From
this point on further calls will return this same error.
@@ -975,7 +1003,7 @@ AVCodecDecoder::_DecodeNextAudioFrameChunk()
{
assert(fDecodedDataBufferSize == 0);

- while(fDecodedDataBufferSize == 0) {
+ while (fDecodedDataBufferSize == 0) {
status_t loadingChunkStatus
= _LoadNextChunkIfNeededAndAssignStartTime();
if (loadingChunkStatus != B_OK)
@@ -1068,9 +1096,7 @@
AVCodecDecoder::_DecodeSomeAudioFramesIntoEmptyDecodedDataBuffer()
if (gotNoAudioFrame)
return B_OK;

- fDecodedDataBufferSize = av_samples_get_buffer_size(NULL,
- fContext->channels, fDecodedDataBuffer->nb_samples,
- fContext->sample_fmt, 1);
+ fDecodedDataBufferSize = fDecodedDataBuffer->nb_samples;
if (fDecodedDataBufferSize < 0)
fDecodedDataBufferSize = 0;

diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h
b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h
index 16906d0..48e6c46 100644
--- a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h
+++ b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h
@@ -4,6 +4,7 @@
* Copyright (C) 2001 Axel Dörfler.
* Copyright (C) 2004 Marcus Overhagen.
* Copyright (C) 2009 Stephan Aßmus <superstippi@xxxxxx>.
+ * Copyright (C) 2015 Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>.
*
* All rights reserved. Distributed under the terms of the MIT License.
*/
@@ -12,13 +13,17 @@

//! libavcodec based decoder for Haiku

+
#include <MediaFormats.h>

+
extern "C" {
#include "avcodec.h"
+ #include "swresample.h"
#include "swscale.h"
}

+
#include "DecoderPlugin.h"
#include "ReaderPlugin.h"

@@ -103,6 +108,7 @@ private:
// FFmpeg related members
AVCodec* fCodec;
AVCodecContext* fContext;
+ SwrContext* fResampleContext;
uint8_t* fDecodedData;
size_t fDecodedDataSizeInBytes;
AVFrame*
fPostProcessedDecodedPicture;
@@ -112,7 +118,9 @@ private:
bool fCodecInitDone;

gfx_convert_func fFormatConversionFunc;
+#if USE_SWS_FOR_COLOR_SPACE_CONVERSION
SwsContext* fSwsContext;
+#endif

char* fExtraData;
int fExtraDataSize;
diff --git a/src/add-ons/media/plugins/ffmpeg/Jamfile
b/src/add-ons/media/plugins/ffmpeg/Jamfile
index c3efdd0..9c3eeaa 100644
--- a/src/add-ons/media/plugins/ffmpeg/Jamfile
+++ b/src/add-ons/media/plugins/ffmpeg/Jamfile
@@ -47,6 +47,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
UseHeaders [ FDirName $(ffmpegHeaders) libavformat ] ;
UseHeaders [ FDirName $(ffmpegHeaders) libavutil ] ;
UseHeaders [ FDirName $(ffmpegHeaders) libswscale ] ;
+ UseHeaders [ FDirName $(ffmpegHeaders) libswresample ] ;

Addon [ MultiArchDefaultGristFiles ffmpeg ] :
$(sources)


Other related posts:

  • » [haiku-commits] haiku: hrev49933 - src/add-ons/media/plugins/ffmpeg - pulkomandy