From 5ae8679e3c9c5f6c83903512e354c914d07083e3 Mon Sep 17 00:00:00 2001 From: "benjamin.drung@gmail.com" Date: Fri, 23 May 2014 20:27:54 +0000 Subject: [PATCH] fix random fixed buffer size and add quick and simple planar import support Signed-off-by: Michael Niedermayer Signed-off-by: Benjamin Drung --- src/FFmpeg.cpp | 69 ++++++++++++++++++++----------------- src/FFmpeg.h | 17 +++++++++ src/import/ImportFFmpeg.cpp | 7 ++++ 3 files changed, 62 insertions(+), 31 deletions(-) diff --git a/src/FFmpeg.cpp b/src/FFmpeg.cpp index 3685edb6c..590b3386f 100644 --- a/src/FFmpeg.cpp +++ b/src/FFmpeg.cpp @@ -478,10 +478,32 @@ int import_ffmpeg_decode_frame(streamContext *sc, bool flushing) } } + AVPacket avpkt; + av_init_packet(&avpkt); + avpkt.data = pDecode; + avpkt.size = nDecodeSiz; + + AVFrame *frame = av_frame_alloc(); + int got_output = 0; + + nBytesDecoded = + avcodec_decode_audio4(sc->m_codecCtx, + frame, // out + &got_output, // out + &avpkt); // in + sc->m_decodedAudioSamplesValidSiz = frame->nb_samples; + + if (nBytesDecoded < 0) + { + // Decoding failed. Don't stop. + return -1; + } + sc->m_samplefmt = sc->m_codecCtx->sample_fmt; sc->m_samplesize = av_get_bits_per_sample_format(sc->m_samplefmt) / 8; - unsigned int newsize = FFMAX(sc->m_pkt.size * sc->m_samplesize, 192000); //FIXME + int channels = sc->m_codecCtx->channels; + unsigned int newsize = sc->m_samplesize * frame->nb_samples * channels; // Reallocate the audio sample buffer if it's smaller than the frame size. if (newsize > sc->m_decodedAudioSamplesSiz ) { @@ -499,38 +521,20 @@ int import_ffmpeg_decode_frame(streamContext *sc, bool flushing) return -1; } } - - - sc->m_decodedAudioSamplesValidSiz = sc->m_decodedAudioSamplesSiz; - -#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(52, 25, 0) - // avcodec_decode_audio3() expects the size of the output buffer as the 3rd parameter but - // also returns the number of bytes it decoded in the same parameter. - AVPacket avpkt; - av_init_packet(&avpkt); - avpkt.data = pDecode; - avpkt.size = nDecodeSiz; - nBytesDecoded = - avcodec_decode_audio3(sc->m_codecCtx, - (int16_t *)sc->m_decodedAudioSamples, // out - &sc->m_decodedAudioSamplesValidSiz, // in/out - &avpkt); // in -#else - // avcodec_decode_audio2() expects the size of the output buffer as the 3rd parameter but - // also returns the number of bytes it decoded in the same parameter. - nBytesDecoded = - avcodec_decode_audio2(sc->m_codecCtx, - (int16_t *) sc->m_decodedAudioSamples, // out - &sc->m_decodedAudioSamplesValidSiz, // in/out - pDecode, // in - nDecodeSiz); // in -#endif - if (nBytesDecoded < 0) - { - // Decoding failed. Don't stop. - return -1; + if (frame->data[1]) { + for (int i = 0; inb_samples; i++) { + for (int ch = 0; chm_decodedAudioSamples + sc->m_samplesize * (ch + channels*i), + frame->extended_data[ch] + sc->m_samplesize*i, + sc->m_samplesize); + } + } + } else { + memcpy(sc->m_decodedAudioSamples, frame->data[0], newsize); } + av_frame_free(&frame); + // We may not have read all of the data from this packet. If so, the user can call again. // Whether or not they do depends on if m_pktRemainingSiz == 0 (they can check). sc->m_pktDataPtr += nBytesDecoded; @@ -1015,6 +1019,7 @@ bool FFmpegLibs::InitLibs(wxString libpath_format, bool WXUNUSED(showerr)) FFMPEG_INITDYN(avcodec, avcodec_find_encoder_by_name); FFMPEG_INITDYN(avcodec, avcodec_find_decoder); FFMPEG_INITDYN(avcodec, avcodec_open2); + FFMPEG_INITDYN(avcodec, avcodec_decode_audio4); #if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(52, 25, 0) FFMPEG_INITDYN(avcodec, avcodec_decode_audio3); #else @@ -1047,6 +1052,8 @@ bool FFmpegLibs::InitLibs(wxString libpath_format, bool WXUNUSED(showerr)) FFMPEG_INITDYN(avutil, av_freep); FFMPEG_INITDYN(avutil, av_rescale_q); FFMPEG_INITDYN(avutil, avutil_version); + FFMPEG_INITDYN(avutil, av_frame_alloc); + FFMPEG_INITDYN(avutil, av_frame_free); wxLogMessage(wxT("All symbols loaded successfully. Initializing the library.")); #endif diff --git a/src/FFmpeg.h b/src/FFmpeg.h index 6a13efd57..86d02cb2e 100644 --- a/src/FFmpeg.h +++ b/src/FFmpeg.h @@ -543,6 +543,12 @@ extern "C" { (AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options), (avctx, codec, options); ); + FFMPEG_FUNCTION_WITH_RETURN( + int, + avcodec_decode_audio4, + (AVCodecContext *avctx, AVFrame *frame, int *got_output, const AVPacket *avpkt), + (avctx, frame, got_output, avpkt) + ); #if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(52, 25, 0) FFMPEG_FUNCTION_WITH_RETURN( int, @@ -874,6 +880,17 @@ extern "C" { (const AVCodec *codec), (codec) ); + FFMPEG_FUNCTION_WITH_RETURN( + AVFrame*, + av_frame_alloc, + (void), + () + ); + FFMPEG_FUNCTION_NO_RETURN( + av_frame_free, + (AVFrame **frame), + (frame) + ); }; #endif diff --git a/src/import/ImportFFmpeg.cpp b/src/import/ImportFFmpeg.cpp index 4ae9f1d5b..f21f1409c 100644 --- a/src/import/ImportFFmpeg.cpp +++ b/src/import/ImportFFmpeg.cpp @@ -493,6 +493,8 @@ int FFmpegImportFileHandle::Import(TrackFactory *trackFactory, { case AV_SAMPLE_FMT_U8: case AV_SAMPLE_FMT_S16: + case AV_SAMPLE_FMT_U8P: + case AV_SAMPLE_FMT_S16P: mScs[s]->m_osamplesize = sizeof(int16_t); mScs[s]->m_osamplefmt = int16Sample; break; @@ -750,22 +752,27 @@ int FFmpegImportFileHandle::WriteData(streamContext *sc) switch (sc->m_samplefmt) { case AV_SAMPLE_FMT_U8: + case AV_SAMPLE_FMT_U8P: ((int16_t *)tmp[chn])[index] = (int16_t) (*(uint8_t *)in - 0x80) << 8; break; case AV_SAMPLE_FMT_S16: + case AV_SAMPLE_FMT_S16P: ((int16_t *)tmp[chn])[index] = (int16_t) *(int16_t *)in; break; case AV_SAMPLE_FMT_S32: + case AV_SAMPLE_FMT_S32P: ((float *)tmp[chn])[index] = (float) *(int32_t *)in * (1.0 / (1 << 31)); break; case AV_SAMPLE_FMT_FLT: + case AV_SAMPLE_FMT_FLTP: ((float *)tmp[chn])[index] = (float) *(float *)in; break; case AV_SAMPLE_FMT_DBL: + case AV_SAMPLE_FMT_DBLP: ((float *)tmp[chn])[index] = (float) *(double *)in; break;