├── audio ├── dtf-tunes.pcm ├── dtf-tunes.wav ├── dtf-tunes4s.pcm ├── dtf-tunes4s.wav ├── dtf-tunes-VBR0.mp3 ├── dtf-tunes-VBR1.mp3 ├── dtf-tunes-VBR2.mp3 ├── dtf-tunes-VBR3.mp3 ├── dtf-tunes-VBR4.mp3 ├── dtf-tunes-cbr128.mp3 ├── dtf-tunes4s-VBR0.mp3 ├── dtf-tunes4s-VBR1.mp3 ├── dtf-tunes4s-VBR2.mp3 ├── dtf-tunes4s-VBR3.mp3 ├── dtf-tunes4s-VBR4.mp3 └── dtf-tunes4s-cbr128.wav ├── autogen.sh ├── compile-pkgconfig.sh ├── Makefile.am ├── compile.sh ├── SConstruct ├── COPYING ├── example3.h ├── example1.h ├── example4.h ├── example3.c ├── configure.ac ├── README.md ├── example2.h ├── CMakeModules └── FindLIBAV.cmake ├── CMakeLists.txt ├── example1.c ├── main.c ├── example2.c └── example4.c /audio/dtf-tunes.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illuusio/ffmpeg-example/HEAD/audio/dtf-tunes.pcm -------------------------------------------------------------------------------- /audio/dtf-tunes.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illuusio/ffmpeg-example/HEAD/audio/dtf-tunes.wav -------------------------------------------------------------------------------- /audio/dtf-tunes4s.pcm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illuusio/ffmpeg-example/HEAD/audio/dtf-tunes4s.pcm -------------------------------------------------------------------------------- /audio/dtf-tunes4s.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illuusio/ffmpeg-example/HEAD/audio/dtf-tunes4s.wav -------------------------------------------------------------------------------- /audio/dtf-tunes-VBR0.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illuusio/ffmpeg-example/HEAD/audio/dtf-tunes-VBR0.mp3 -------------------------------------------------------------------------------- /audio/dtf-tunes-VBR1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illuusio/ffmpeg-example/HEAD/audio/dtf-tunes-VBR1.mp3 -------------------------------------------------------------------------------- /audio/dtf-tunes-VBR2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illuusio/ffmpeg-example/HEAD/audio/dtf-tunes-VBR2.mp3 -------------------------------------------------------------------------------- /audio/dtf-tunes-VBR3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illuusio/ffmpeg-example/HEAD/audio/dtf-tunes-VBR3.mp3 -------------------------------------------------------------------------------- /audio/dtf-tunes-VBR4.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illuusio/ffmpeg-example/HEAD/audio/dtf-tunes-VBR4.mp3 -------------------------------------------------------------------------------- /audio/dtf-tunes-cbr128.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illuusio/ffmpeg-example/HEAD/audio/dtf-tunes-cbr128.mp3 -------------------------------------------------------------------------------- /audio/dtf-tunes4s-VBR0.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illuusio/ffmpeg-example/HEAD/audio/dtf-tunes4s-VBR0.mp3 -------------------------------------------------------------------------------- /audio/dtf-tunes4s-VBR1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illuusio/ffmpeg-example/HEAD/audio/dtf-tunes4s-VBR1.mp3 -------------------------------------------------------------------------------- /audio/dtf-tunes4s-VBR2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illuusio/ffmpeg-example/HEAD/audio/dtf-tunes4s-VBR2.mp3 -------------------------------------------------------------------------------- /audio/dtf-tunes4s-VBR3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illuusio/ffmpeg-example/HEAD/audio/dtf-tunes4s-VBR3.mp3 -------------------------------------------------------------------------------- /audio/dtf-tunes4s-VBR4.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illuusio/ffmpeg-example/HEAD/audio/dtf-tunes4s-VBR4.mp3 -------------------------------------------------------------------------------- /audio/dtf-tunes4s-cbr128.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/illuusio/ffmpeg-example/HEAD/audio/dtf-tunes4s-cbr128.wav -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | libtoolize --copy --force 3 | aclocal --force 4 | automake --copy --force --add-missing 5 | autoconf --force 6 | -------------------------------------------------------------------------------- /compile-pkgconfig.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | RESAMPLER=__LIBAVRESAMPLE__ 3 | #RESAMPLER=__LIBSWRESAMPLE__ 4 | #RESAMPLER=__FFMPEGOLDAPI__ 5 | RESAMPLER_LIB=avresample 6 | # RESAMPLER_LIB=swresample 7 | # RESAMPLER_LIB= 8 | 9 | echo "$(pkg-config --libs --cflags ${RESAMPLER_LIB} libavcodec libavformat libavutil) -lm -g -D${RESAMPLER} -std=c99 -I." 10 | 11 | 12 | gcc -o ffmpeg-example-bin example1.c example2.c example3.c example4.c main.c \ 13 | $(pkg-config --libs --cflags ${RESAMPLER_LIB} libavcodec libavformat libavutil) -lm -g -D${RESAMPLER} -std=c99 -I. 14 | 15 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | AM_CPPFLAGS = $(FFMPEG_CFLAGS) $(C_OPTIONS) -D_POSIX_SOURCE -D_USE_XOPEN -D_USE_MISC 2 | ACLOCAL_AMFLAGS = -I m4 3 | 4 | EXTRA_DIST = COPYING compile-pkgconfig.sh compile.sh CMakeLists.txt CMakeModules/FindFFmpeg.cmake SConstruct autogen.sh m4/* 5 | 6 | 7 | bin_PROGRAMS = ffmpeg-example-bin 8 | # sbin_PROGRAMS = ffmpeg-example-bin 9 | # noinst_PROGRAMS = ffmpeg-example-bin 10 | 11 | ffmpeg_example_bin_SOURCES = example1.c example2.c example3.c example4.c main.c example1.h example2.h example3.h example4.h 12 | ffmpeg_example_bin_LDFLAGS = $(FFMPEG_LIBS) -lm 13 | 14 | -------------------------------------------------------------------------------- /compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RESAMPLER=_"_LIBAVRESAMPLE__" 4 | #RESAMPLER="__LIBSWRESAMPLE__" 5 | #RESAMPLER="__FFMPEGOLDAPI__" 6 | RESAMPLER_LIB="avresample" 7 | # RESAMPLER_LIB="swresample" 8 | # RESAMPLER_LIB= 9 | 10 | FFMPEG_INCLUDE=/usr/include/ffmpeg 11 | FFMPEG_VERSION=$(pkg-config --modversion libavcodec | tr -d '.') 12 | 13 | if [ ${FFMPEG_VERSION} -ge 5818100 ] 14 | then 15 | echo "FFMpeg Version is bigger than 4.0.1. Which to SWResample because AVResample is depricated." 16 | RESAMPLER_LIB="swresample" 17 | RESAMPLER="__LIBSWRESAMPLE__" 18 | fi 19 | 20 | gcc -o ffmpeg-example-bin example1.c example2.c example3.c example4.c main.c -l${RESAMPLER_LIB} \ 21 | -lavcodec -lavformat -lavutil -lm -g -D${RESAMPLER} -std=c99 -I. -I${FFMPEG_INCLUDE} 22 | -------------------------------------------------------------------------------- /SConstruct: -------------------------------------------------------------------------------- 1 | # Compile ffmpeg-example-bin 2 | # Because FFmpeg 4.0 Depricates AVResample you have to change __LIBAVRESAMPLE__ 3 | # to __LIBSWRESAMPLE__ to make this compile 4 | env = Environment(CPPPATH = ['.'], CCFLAGS='-Wall -Werror -std=c99 -fno-strict-aliasing -I/usr/include/ffmpeg -g -D__LIBSWRESAMPLE__ -std=c99') 5 | # env = Environment(CPPPATH = ['.'], CCFLAGS='-Wall -Werror -std=c99 -fno-strict-aliasing -I/usr/include/ffmpeg -g -D__LIBAVRESAMPLE__ -std=c99') 6 | #env.Program(target = "ffmpeg-example-bin", LIBS=["avresample" ,"avcodec", "avformat", "avutil", "m"], 7 | # source = ["example1.c", "example2.c", "example3.c", "example4.c", "main.c"]) 8 | env.Program(target = "ffmpeg-example-bin", LIBS=["swresample" ,"avcodec", "avformat", "avutil", "m"], 9 | source = ["example1.c", "example2.c", "example3.c", "example4.c", "main.c"]) 10 | 11 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2003, Tuukka Pasanen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /example3.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Tuukka Pasanen 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef FFMPEGEXAMPLE3_H 22 | #define FFMPEGEXAMPLE3_H 23 | 24 | #include 25 | #include 26 | 27 | double fe_convert_toByteOffset(double pts, unsigned int samplerate, const AVRational *ffmpegtime); 28 | double fe_convert_fromByteOffset(double byteoffset, unsigned int samplerate, const AVRational *ffmpegtime); 29 | 30 | #endif -------------------------------------------------------------------------------- /example1.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Tuukka Pasanen 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef FFMPEGEXAMPLE_H 22 | #define FFMPEGEXAMPLE_H 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | extern AVFormatContext *m_pFormatCtx; 29 | extern AVInputFormat *m_pIformat; 30 | extern AVCodecContext *m_pCodecCtx; 31 | extern int m_iAudioStream; 32 | extern AVCodec *m_pCodec; 33 | extern int64_t m_lPcmLength; 34 | 35 | int fe_decode_open(char *filename); 36 | 37 | #endif -------------------------------------------------------------------------------- /example4.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Tuukka Pasanen 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #ifndef FFMPEGEXAMPLE4_H 22 | #define FFMPEGEXAMPLE4_H 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | extern int64_t m_iSeekOffset; 29 | extern int64_t m_iLastFirstFfmpegByteOffset; 30 | extern int64_t m_iCurrentMixxTs; 31 | extern int64_t m_iOffset; 32 | extern int m_bIsSeeked; 33 | 34 | long fe_read_seek(long filepos); 35 | unsigned int fe_read_frame(char *buffer, int size); 36 | 37 | #endif -------------------------------------------------------------------------------- /example3.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Tuukka Pasanen 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #include "example3.h" 22 | 23 | 24 | double fe_convert_toByteOffset(double pts, unsigned int samplerate, const AVRational *ffmpegtime) { 25 | return (pts / (double)ffmpegtime->den * (double)samplerate * 26 | (double)2.); 27 | } 28 | 29 | double fe_convert_fromByteOffset(double byteoffset, unsigned int samplerate, const AVRational *ffmpegtime) { 30 | return (byteoffset / (double)samplerate / (double)2.) * 31 | (double)ffmpegtime->den; 32 | } 33 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_PREREQ([2.57]) 2 | AC_INIT([ffmpeg-example], [201119], [https://github.com/illuusio/ffmpeg-example], [ffmpeg-example], [https://github.com/illuusio/ffmpeg-example]) 3 | AM_INIT_AUTOMAKE([foreign dist-bzip2]) 4 | AC_CONFIG_MACRO_DIR([m4]) 5 | 6 | AC_LANG_C 7 | AC_PROG_CC 8 | AM_PROG_LIBTOOL 9 | 10 | RESAMPLE=__LIBAVRESAMPLE__ 11 | RESAMPLELIB=libavresample 12 | 13 | AC_ARG_ENABLE([avresample], [ --disable-avresample Disable use of avresample]) 14 | AC_ARG_ENABLE([swresample], [ --enable-swresample Disable use of avresample and use libswresample instead]) 15 | 16 | PKG_CHECK_MODULES([FFMEG_LIBAVCODEC],[libavcodec], 17 | [ac_libavcodec_version=$($PKG_CONFIG --modversion libavcodec | tr -d '.')], 18 | [ac_libavcodec_version=;]) 19 | 20 | if test "${ac_libavcodec_version}" -ge "5818100"; then 21 | echo "FFMpeg Version is bigger than 4.0.1. Which to SWResample because AVResample is depricated." 22 | RESAMPLELIB="libswresample" 23 | RESAMPLE="__LIBSWRESAMPLE__" 24 | fi 25 | 26 | 27 | AS_IF([test "x$enable_avresample" == "xno"], [ 28 | dnl As we don't need education we disable this feature 29 | echo "** We are using OLD FFMPEG resampling. Not working with FFMPEG 1.x and above (Libav 9) **" 30 | RESAMPLE=__FFMPEGOLDAPI__ 31 | RESAMPLELIB= 32 | ]) 33 | 34 | AS_IF([test "x$enable_swresample" == "xyes"], [ 35 | dnl As we don't need education we disable this feature 36 | echo "** We are using SWResample good luck **" 37 | RESAMPLE=__LIBSWRESAMPLE__ 38 | RESAMPLELIB=libswresample 39 | ]) 40 | 41 | 42 | C_OPTIONS="-Wall -Werror -std=c99 -fno-strict-aliasing -g -D${RESAMPLE} -std=c99 -I." 43 | 44 | AC_SUBST(C_OPTIONS) 45 | 46 | 47 | PKG_CHECK_MODULES(FFMPEG, ${RESAMPLELIB} libavcodec libavformat libavutil) 48 | 49 | AC_OUTPUT([Makefile]) 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | FFmpeg-example 2 | ============== 3 | 4 | [FFmpeg](http://ffmpeg.org/) 0.11-4.0 or [Libav](http://libav.org/) 0.8-11 example application with byte exact reading 5 | 6 | FFmpeg/Libav example program 7 | ============================ 8 | 9 | This program is example how to use FFmpeg or Libav library with Byte exact reading (Audio only!). Tested with 'gcc'. 10 | Currently it only outputs 'out-for.pcm' and 'out-rev.pcm' files that are in Stereo 16-bit raw audio files (s16) that 11 | can be opened with Audacity audio editor or similar which imports raw PCM audio. 12 | 13 | Compiling with CMake 14 | ------------------- 15 | You need to have FFmpeg or Libav installed. You need [CMake](http://cmake.org/) and [pkg-config](http://www.freedesktop.org/wiki/Software/pkg-config/). 16 |
17 | cmake .
18 | 
19 | If everything goes fine 20 |
21 | make
22 | 
23 | 24 | Compiling with autotools 25 | ------------------------ 26 | You need to have FFmpeg or Libav installed. You need have [GNU autotools](http://www.gnu.org/savannah-checkouts/gnu/automake/manual/html_node/Autotools-Introduction.html), [pkg-config](http://www.freedesktop.org/wiki/Software/pkg-config/) and [libtools](http://www.gnu.org/software/libtool/) 27 | installed. 28 |
29 | ./autogen.sh
30 | ./configure
31 | 
32 | If everything goes fine 33 |
34 | make
35 | 
36 | 37 | Compiling with scons 38 | -------------------- 39 | You need to have FFmpeg or Libav installed. You need have [SCons](http://www.scons.org/) and [pkg-config](http://www.freedesktop.org/wiki/Software/pkg-config/). 40 |
41 | scons
42 | 
43 | 44 | Compiling with script 45 | --------------------- 46 | You need to have FFmpeg or Libav installed. You need have [pkg-config](http://www.freedesktop.org/wiki/Software/pkg-config/). 47 |
48 | ./compile-pkgconfig.sh
49 | 
50 | 51 | Running application 52 | =================== 53 | Currently tested files are OGG/Vorbis,MP3 and MP4 (also acc). 54 | 55 |
56 | ./FFmpeg-example-bin audio-file
57 | 
58 | 59 | You get as output 'out-for.pcm' and 'out-rev.pcm' files that contains played forward byte exact and 60 | reverse played file (as audio is normal!) 61 | -------------------------------------------------------------------------------- /example2.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Tuukka Pasanen 2 | // All rights reserved. 3 | // 4 | // Copyright (c) 2013, Tuukka Pasanen 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #ifndef FFMPEGEXAMPLE2_H 25 | #define FFMPEGEXAMPLE2_H 26 | 27 | #include 28 | #include 29 | 30 | // Thank you macports not providing libavresample for FFMPEG! 31 | #ifdef __LIBAVRESAMPLE__ 32 | #include 33 | #else 34 | #include 35 | #endif 36 | 37 | int fe_resample_open(enum AVSampleFormat inSampleFmt, 38 | enum AVSampleFormat outSampleFmt); 39 | 40 | unsigned int fe_resample_do(AVFrame *inframe); 41 | 42 | 43 | extern AVCodecContext *m_pCodecCtx; 44 | extern enum AVSampleFormat m_pOutSampleFmt; 45 | extern enum AVSampleFormat m_pInSampleFmt; 46 | 47 | 48 | #ifndef __FFMPEGOLDAPI__ 49 | 50 | // Please choose to use libavresample.. people 51 | // Compile it now.. but because macports doesn't 52 | // Support both.. damn! 53 | #ifdef __LIBAVRESAMPLE__ 54 | extern AVAudioResampleContext *m_pSwrCtx; 55 | #else 56 | extern SwrContext *m_pSwrCtx; 57 | #endif 58 | extern uint8_t *m_pOut; 59 | #else 60 | extern ReSampleContext *m_pSwrCtx; 61 | extern short *m_pOut; 62 | #endif 63 | 64 | extern unsigned int m_pOutSize; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /CMakeModules/FindLIBAV.cmake: -------------------------------------------------------------------------------- 1 | # Find ffmpeg/libav libraries (libavcodec, libavformat and libavutil) 2 | # Once done this will define 3 | # 4 | # LIBAV_FOUND - system has libavcodec, libavformat, libavutil 5 | # LIBAV_INCLUDE_DIR - libav include directories 6 | # LIBAV_LIBRARIES - libav libraries (libavcodec, libavformat, libavutil) 7 | # 8 | # LIBAVCODEC_LIBRARY - libavcodec library 9 | # LIBAVCODEC_INCLUDE_DIR - libavcodec include directory 10 | # LIBAVFORMAT_LIBRARY - libavformat library 11 | # LIBAVUTIL_LIBRARY - libavutil library 12 | # 13 | # Copyright (c) 2008 Andreas Schneider 14 | # Modified for other libraries by Lasse Kärkkäinen 15 | # Modified for Hedgewars by Stepik777 16 | # Copyright (c) 2013 Vittorio Giovara 17 | # 18 | # This once is from Hedgewars 19 | # https://github.com/hedgewars/hw/blob/master/cmake_modules/FindLIBAV.cmake 20 | # 21 | # Redistribution and use is allowed according to the terms of the New 22 | # BSD license. 23 | # 24 | 25 | include(FindPackageHandleStandardArgs) 26 | 27 | 28 | # use pkg-config to get the directories and then use these values 29 | # in the FIND_PATH() and FIND_LIBRARY() calls 30 | find_package(PkgConfig) 31 | if(PKG_CONFIG_FOUND) 32 | if(NOT LIBAVCODEC_INCLUDE_DIR OR NOT LIBAVCODEC_LIBRARY) 33 | pkg_check_modules(_LIBAV_AVCODEC libavcodec) 34 | endif() 35 | if(NOT LIBAVFORMAT_LIBRARY) 36 | pkg_check_modules(_LIBAV_AVFORMAT libavformat) 37 | endif() 38 | if(NOT LIBAVUTIL_LIBRARY) 39 | pkg_check_modules(_LIBAV_AVUTIL libavutil) 40 | endif() 41 | endif(PKG_CONFIG_FOUND) 42 | 43 | find_path(LIBAVCODEC_INCLUDE_DIR 44 | NAMES libavcodec/avcodec.h 45 | PATHS ${_LIBAV_AVCODEC_INCLUDE_DIRS} #pkg-config 46 | /usr/include /usr/local/include #system level 47 | /opt/local/include /sw/include #macports & fink 48 | PATH_SUFFIXES libav ffmpeg 49 | ) 50 | 51 | #TODO: add other include paths 52 | 53 | find_library(LIBAVCODEC_LIBRARY 54 | NAMES avcodec 55 | PATHS ${_LIBAV_AVCODEC_LIBRARY_DIRS} #pkg-config 56 | /usr/lib /usr/local/lib #system level 57 | /opt/local/lib /sw/lib #macports & fink 58 | ) 59 | 60 | find_library(LIBAVFORMAT_LIBRARY 61 | NAMES avformat 62 | PATHS ${_LIBAV_AVFORMAT_LIBRARY_DIRS} #pkg-config 63 | /usr/lib /usr/local/lib #system level 64 | /opt/local/lib /sw/lib #macports & fink 65 | ) 66 | 67 | find_library(LIBAVUTIL_LIBRARY 68 | NAMES avutil 69 | PATHS ${_LIBAV_AVUTIL_LIBRARY_DIRS} #pkg-config 70 | /usr/lib /usr/local/lib #system level 71 | /opt/local/lib /sw/lib #macports & fink 72 | ) 73 | 74 | find_package_handle_standard_args(LIBAV DEFAULT_MSG LIBAVCODEC_LIBRARY 75 | LIBAVCODEC_INCLUDE_DIR 76 | LIBAVFORMAT_LIBRARY 77 | LIBAVUTIL_LIBRARY 78 | ) 79 | set(LIBAV_INCLUDE_DIR ${LIBAVCODEC_INCLUDE_DIR} 80 | #TODO: add other include paths 81 | ) 82 | set(LIBAV_LIBRARIES ${LIBAVCODEC_LIBRARY} 83 | ${LIBAVFORMAT_LIBRARY} 84 | ${LIBAVUTIL_LIBRARY} 85 | ) 86 | 87 | mark_as_advanced(LIBAV_INCLUDE_DIR 88 | LIBAV_LIBRARIES 89 | LIBAVCODEC_LIBRARY 90 | LIBAVCODEC_INCLUDE_DIR 91 | LIBAVFORMAT_LIBRARY 92 | LIBAVUTIL_LIBRARY) 93 | 94 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(ffmpeg-examples) 2 | 3 | cmake_minimum_required(VERSION 3.0) 4 | 5 | set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules) 6 | 7 | #versioning 8 | set(CPACK_PACKAGE_VERSION_MAJOR 20) 9 | set(CPACK_PACKAGE_VERSION_MINOR 11) 10 | set(CPACK_PACKAGE_VERSION_PATCH 19) 11 | set(FFMPEGEXAMPLE_PROTO_VER 0) 12 | set(FFMPEGEXAMPLE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.\ 13 | ${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") 14 | 15 | set(target_dir "bin") 16 | 17 | # set default flags values for all projects 18 | # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") 19 | # set(CMAKE_C_FLAGS_RELEASE 20 | # "-w -Os -fomit-frame-pointer ${CMAKE_C_FLAGS_RELEASE}") 21 | # set(CMAKE_C_FLAGS_DEBUG 22 | # "-Wall -O0 -g -DDEBUG ${CMAKE_C_FLAGS_DEBUG}") 23 | # set(CMAKE_CXX_FLAGS ${CMAKE_C_FLAGS}) 24 | # set(CMAKE_CXX_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE}) 25 | # set(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG}) 26 | 27 | add_executable(ffmpeg-example-bin 28 | example1.c 29 | example2.c 30 | example3.c 31 | example4.c 32 | main.c) 33 | 34 | include_directories(".") 35 | # find_package(FFmpeg REQUIRED) 36 | find_package(LIBAV REQUIRED) 37 | 38 | # LIBAV_FOUND - system has ffmpeg or libav 39 | # LIBAV_INCLUDE_DIR - the ffmpeg include directory 40 | # LIBAV_LIBRARIES 41 | # LIBAV_LIBAVCODEC 42 | # LIBAV_LIBAVFORMAT 43 | # LIBAV_LIBAVUTIL 44 | if(LIBAV_FOUND) 45 | message("Found FFMPEG/LibAV libraries") 46 | include_directories(${LIBAV_INCLUDE_DIR}) 47 | target_link_libraries(ffmpeg-example-bin ${LIBAV_LIBRARIES}) 48 | else() 49 | message("Can't find libavcodec, libavformat or libavutil. Add them!") 50 | endif() 51 | 52 | target_link_libraries(ffmpeg-example-bin "-lm") 53 | 54 | option(LIBAV_AVRESAMPLE "Use AvResample not SWResample (depricated with 4.0.1) (off)" OFF) 55 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -std=c99") 56 | 57 | if(LIBAV_AVRESAMPLE) 58 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__LIBAVRESAMPLE__") 59 | target_link_libraries(ffmpeg-example-bin "-lavresample") 60 | else() 61 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__LIBSWRESAMPLE__") 62 | target_link_libraries(ffmpeg-example-bin "-lswresample") 63 | endif() 64 | 65 | 66 | 67 | # CPack variables 68 | set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "FFMPEG example CMake file") 69 | set(CPACK_PACKAGE_VENDOR "Tuukka Pasanen ") 70 | set(CPACK_PACKAGE_FILE_NAME "ffmpeg-example-${FFMPEGEXAMPLE_VERSION}") 71 | set(CPACK_SOURCE_PACKAGE_FILE_NAME "ffmpeg-example-src-${FFMPEGEXAMPLE_VERSION}") 72 | set(CPACK_SOURCE_GENERATOR "TBZ2") 73 | set(CPACK_PACKAGE_EXECUTABLES "ffmpeg-example-bin") 74 | set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") 75 | set(CPACK_PACKAGE_INSTALL_DIRECTORY 76 | "ffmpeg-example ${CPACK_PACKAGE_VERSION_MAJOR}.\ 77 | ${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") 78 | 79 | if(WIN32 AND NOT UNIX) 80 | set(CPACK_NSIS_DISPLAY_NAME "FFMPEG Example") 81 | set(CPACK_NSIS_HELP_LINK "https://github.com/illuusio/ffmpeg-example") 82 | set(CPACK_NSIS_URL_INFO_ABOUT "https://github.com/illuusio/ffmpeg-example") 83 | set(CPACK_NSIS_CONTACT "tuukka.pasanen@ilmi.fi") 84 | set(CPACK_NSIS_MODIFY_PATH OFF) 85 | set(CPACK_GENERATOR "ZIP;NSIS") 86 | set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "ffmpeg-example") 87 | else() 88 | set(CPACK_STRIP_FILES "bin/ffmpeg-example") 89 | endif() 90 | 91 | set(CPACK_SOURCE_IGNORE_FILES 92 | "~" 93 | "\\\\.hg" 94 | "\\\\.svn" 95 | "\\\\.exe$" 96 | "\\\\.a$" 97 | "\\\\.dll$" 98 | "\\\\.xcf$" 99 | "\\\\.cxx$" 100 | "\\\\.db$" 101 | "\\\\.dof$" 102 | "\\\\.layout$" 103 | "\\\\.zip$" 104 | "\\\\.gz$" 105 | "\\\\.bz2$" 106 | "\\\\.tmp$" 107 | "\\\\.core$" 108 | "\\\\.sh$" 109 | "\\\\.sifz$" 110 | "\\\\.svg$" 111 | "\\\\.svgz$" 112 | "\\\\.ppu$" 113 | "\\\\.psd$" 114 | "\\\\.o$" 115 | "Makefile" 116 | "Doxyfile" 117 | "CMakeFiles" 118 | "debug" 119 | "release$" 120 | "Debug$" 121 | "Release$" 122 | "proto\\\\.inc$" 123 | "hwconsts\\\\.cpp$" 124 | "playlist\\\\.inc$" 125 | "CPack" 126 | "cmake_install\\\\.cmake$" 127 | "config\\\\.inc$" 128 | "CMakeCache\\\\.txt$" 129 | "^${CMAKE_CURRENT_SOURCE_DIR}/misc/liblua" 130 | "^${CMAKE_CURRENT_SOURCE_DIR}/install_manifest.txt" 131 | "^${CMAKE_CURRENT_SOURCE_DIR}/CMakeCache.txt" 132 | ) 133 | 134 | include(CPack) 135 | 136 | -------------------------------------------------------------------------------- /example1.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Tuukka Pasanen 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #include 22 | 23 | AVFormatContext *m_pFormatCtx = NULL; 24 | AVInputFormat *m_pIformat = NULL; 25 | AVCodecContext *m_pCodecCtx = NULL; 26 | int m_iAudioStream = -1; 27 | AVCodec *m_pCodec = NULL; 28 | int64_t m_lPcmLength = 0; 29 | 30 | int fe_decode_open(char *filename) { 31 | int i = -1; 32 | AVDictionary *l_iFormatOpts = NULL; 33 | 34 | printf("fe_decode_open: Decode audio file %s\n", 35 | filename); 36 | 37 | m_pFormatCtx = avformat_alloc_context(); 38 | 39 | // Enable this to use old slow MP3 Xing TOC 40 | #ifndef CODEC_ID_MP3 41 | 42 | if ( LIBAVFORMAT_VERSION_INT > 3540580 ) { 43 | printf("fe_decode_open: Set usetoc to have old way of XING TOC reading (libavformat version: '%d')\n", LIBAVFORMAT_VERSION_INT); 44 | av_dict_set(&l_iFormatOpts, "usetoc", "0", 0); 45 | } 46 | 47 | #endif 48 | 49 | // Open file and make m_pFormatCtx 50 | if (avformat_open_input(&m_pFormatCtx, filename, NULL, &l_iFormatOpts) != 0) { 51 | printf("fe_decode_open: cannot open with 'avformat_open_input': %s\n", 52 | filename); 53 | return -1; 54 | } 55 | 56 | #ifndef CODEC_ID_MP3 57 | 58 | if ( LIBAVFORMAT_VERSION_INT > 3540580 && l_iFormatOpts != NULL ) { 59 | av_dict_free(&l_iFormatOpts); 60 | } 61 | 62 | #endif 63 | 64 | #if LIBAVCODEC_VERSION_INT < 3622144 65 | m_pFormatCtx->max_analyze_duration = 999999999; 66 | #endif 67 | 68 | // Retrieve stream information 69 | if (avformat_find_stream_info(m_pFormatCtx, NULL) < 0) { 70 | printf("fe_decode_open: cannot open find info '%s'\n", 71 | filename); 72 | printf("As documentation says this is pretty normal. So this not show stopper!\n"); 73 | } 74 | 75 | av_dump_format(m_pFormatCtx, 0, filename, 0); 76 | 77 | // Find the first video stream 78 | m_iAudioStream = -1; 79 | 80 | printf("fe_decode_open: File got streams: %d\n", m_pFormatCtx->nb_streams); 81 | 82 | for (i = 0; i < m_pFormatCtx->nb_streams; i++) { 83 | // If we have FFMpeg version which is less than 3.2 then we use older implementation 84 | #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 0) 85 | if (m_pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { 86 | #else 87 | 88 | if (m_pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { 89 | #endif 90 | m_iAudioStream = i; 91 | break; 92 | } 93 | } 94 | 95 | if (m_iAudioStream == -1) { 96 | printf("fe_decode_open: cannot find an audio stream: cannot open %s", 97 | filename); 98 | return -1; 99 | } 100 | 101 | // Find the decoder for the audio stream 102 | // If we have FFMpeg version which is less than 3.2 then we use older implementation 103 | #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 0) 104 | 105 | if (!(m_pCodec = avcodec_find_decoder(m_pFormatCtx->streams[m_iAudioStream]->codec_id))) { 106 | #else 107 | 108 | if (!(m_pCodec = avcodec_find_decoder(m_pFormatCtx->streams[m_iAudioStream]->codecpar->codec_id))) { 109 | #endif 110 | printf("fe_decode_open: cannot find a decoder for %s\n", 111 | filename); 112 | return -1; 113 | } 114 | 115 | // If we have FFMpeg version which is less than 3.2 then we use older implementation 116 | #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 0) 117 | // Get a pointer to the codec context for the video stream 118 | m_pCodecCtx = m_pFormatCtx->streams[m_iAudioStream]->codec; 119 | 120 | #else 121 | // Get a pointer to the codec context for the video stream 122 | //m_pCodecCtx = avcodec_alloc_context3(m_pCodec); 123 | m_pCodecCtx = avcodec_alloc_context3(NULL); 124 | 125 | // Add stream parameters to context 126 | if(avcodec_parameters_to_context(m_pCodecCtx, m_pFormatCtx->streams[m_iAudioStream]->codecpar)) { 127 | printf("fe_decode_open: cannot add Codec parameters: %s\n", 128 | filename); 129 | return -1; 130 | } 131 | 132 | // This is not needed anymore above FFMpeg version 4.0 133 | #if LIBAVCODEC_VERSION_INT < 3805796 134 | // Se timebase correct 135 | av_codec_set_pkt_timebase(m_pCodecCtx, m_pFormatCtx->streams[m_iAudioStream]->time_base); 136 | #endif 137 | 138 | // Make sure that Codecs are identical or avcodec_open2 fails. 139 | m_pCodecCtx->codec_id = m_pCodec->id; 140 | #endif 141 | 142 | if(!m_pCodecCtx) { 143 | printf("fe_decode_open: cannot get 'AVCodecContext'\n"); 144 | return -1; 145 | } 146 | 147 | if (avcodec_open2(m_pCodecCtx, m_pCodec, NULL) < 0) { 148 | printf("fe_decode_open: cannot open with 'avcodec_open2' codec_id: %d Audio stream id: %d: %s\n", 149 | m_pFormatCtx->streams[m_iAudioStream]->codecpar->codec_id, 150 | m_iAudioStream, filename 151 | ); 152 | return -1; 153 | } 154 | 155 | printf("fe_decode_open: PCM Length is: %f (Bytes: %ld)\n", 156 | (double)(m_pFormatCtx->duration / AV_TIME_BASE), 157 | (int64_t)round((double)(m_pFormatCtx->duration / AV_TIME_BASE) * (44100 * 4))); 158 | m_lPcmLength = (int64_t)round((double)(m_pFormatCtx->duration / AV_TIME_BASE) * (44100 * 4)); 159 | 160 | return 0; 161 | } 162 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Tuukka Pasanen 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #define FFMPEG_EXAMPLE_STEP 32768 22 | 23 | #include "example1.h" 24 | #include "example2.h" 25 | #include "example3.h" 26 | #include "example4.h" 27 | 28 | int main(int argc, char * argv[]) { 29 | //int64_t i = 0; 30 | int64_t j = 0; 31 | 32 | //fe_read_seek(0); 33 | char l_strBuffer[(FFMPEG_EXAMPLE_STEP * 2)]; 34 | char l_strBuffer2[(FFMPEG_EXAMPLE_STEP * 2)]; 35 | FILE *l_pOutFile = NULL; 36 | int l_iReadSize = 0; 37 | //int64_t l_iRead = 200; 38 | //int64_t l_iStart = 1000; 39 | //int64_t l_iStartCur = 0; 40 | //int64_t l_iReadCur = 0; 41 | //int64_t l_iStartUp = 0; 42 | //int64_t l_iStartDown = 0; 43 | //int64_t l_iSeekDirection = 0; 44 | //int64_t l_iSeekStep = 50; 45 | 46 | int64_t l_lSeekStartPoint = 0; 47 | //int64_t l_lSeekMiddleLowPoint = 0; 48 | //int64_t l_lSeekMiddleHighPoint = 0; 49 | //int64_t l_lSeekEndPoint = 0; 50 | 51 | // FFMPEG uses SOMETHING_MICRO > 100 and Avconv under 52 | #if LIBAVCODEC_VERSION_MICRO >= 100 53 | printf("Using Library: FFmpeg\n"); 54 | #else 55 | printf("Using Library: Avconv\n"); 56 | #endif 57 | 58 | printf("libavcodec version %d.%d.%d (%d)\n", LIBAVCODEC_VERSION_MAJOR, 59 | LIBAVCODEC_VERSION_MINOR, 60 | LIBAVCODEC_VERSION_MICRO, 61 | LIBAVCODEC_VERSION_INT); 62 | printf("libavformat version %d.%d.%d (%d)\n", LIBAVFORMAT_VERSION_MAJOR, 63 | LIBAVFORMAT_VERSION_MINOR, 64 | LIBAVFORMAT_VERSION_MICRO, 65 | LIBAVFORMAT_VERSION_INT); 66 | 67 | 68 | if( argc < 2 ) { 69 | printf("Usage: ffmpeg-example-bin audio.mp3/wav/flac/ogg/opus/m4v/aac\n"); 70 | printf("\nOpen with audacity file: 'out-f.pcm' (import raw data)\n"); 71 | printf("Stereo 16 Bit / Little Endian / 2 channels\n"); 72 | return 0; 73 | } 74 | 75 | // Below FFmpeg 4.0.1 we need to register all before use 76 | #if LIBAVCODEC_VERSION_INT < 3805796 77 | av_register_all(); 78 | avcodec_register_all(); 79 | #endif 80 | 81 | if(fe_decode_open(argv[1]) < 0) { 82 | printf("main: Can't open file exiting!\n"); 83 | return -1; 84 | } 85 | 86 | fe_resample_open(m_pCodecCtx->sample_fmt, AV_SAMPLE_FMT_S16); 87 | 88 | l_pOutFile = fopen("out-for.pcm", "w+"); 89 | 90 | // l_lSeekMiddleLowPoint = l_lSeekMiddleHighPoint = (m_lPcmLength / 2); 91 | 92 | 93 | memset(l_strBuffer, 0x99, (FFMPEG_EXAMPLE_STEP * 2)); 94 | memset(l_strBuffer2, 0x88, (FFMPEG_EXAMPLE_STEP * 2)); 95 | 96 | for( j = 0; j < 2; j ++) { 97 | printf("main: Ask reading %ld (23040 bytes)\n", l_lSeekStartPoint); 98 | fe_read_seek(l_lSeekStartPoint); 99 | //l_iReadSize = fe_read_frame(l_strBuffer, FFMPEG_EXAMPLE_STEP); 100 | l_iReadSize = fe_read_frame(l_strBuffer, 23040); 101 | // fseek( l_pOutFile, l_lSeekStartPoint, SEEK_SET); 102 | fwrite(l_strBuffer, l_iReadSize, 1, l_pOutFile); 103 | fwrite(l_strBuffer2, 1024, 1, l_pOutFile); 104 | //l_lSeekStartPoint += FFMPEG_EXAMPLE_STEP; 105 | l_lSeekStartPoint += 23040; 106 | 107 | 108 | } 109 | 110 | 111 | 112 | /*for( i = l_iStart; i < l_iRead; i ++) { 113 | fwrite(l_strBuffer, 4608, 1, l_pOutFile); 114 | } 115 | 116 | // We start reading at the half of file our wanted area.. 117 | l_iStartCur = l_iStart + (l_iRead / 2); 118 | l_iReadCur = l_iRead / l_iSeekStep; 119 | 120 | //av_opt_show2(&m_pFormatCtx->iformat->priv_class, NULL, AV_OPT_FLAG_DECODING_PARAM, 0); 121 | 122 | // This example stars from middle and then seeks forward and 123 | // backward 124 | for( j = 0; j < 50; j++ ) { 125 | printf("Start: %ld Read: %ld\n", l_iStartCur, l_iReadCur); 126 | 127 | for( i = 0; i <= l_iReadCur; i ++) { 128 | memset(l_strBuffer, 0x00, 65355); 129 | printf("Loop: %ld/%ld (@%ld of %ld)\n", j, i, (2304 * (i + l_iStartCur)), m_lPcmLength); 130 | fe_read_seek(2304 * (i + l_iStartCur)); 131 | l_iReadSize = fe_read_frame(l_strBuffer, 2304); 132 | fseek( l_pOutFile, (2304 * 2) * (i + l_iStartCur), SEEK_SET); 133 | fwrite(l_strBuffer, l_iReadSize, 1, l_pOutFile); 134 | // If you like to see what we just read eanble this.. 135 | //memset(l_strBuffer, 0x77, 65355); 136 | // fwrite(l_strBuffer, 100, 1, l_pOutFile); 137 | } 138 | 139 | if( l_iStartDown == 0 || l_iStartDown > l_iStartCur ) { 140 | l_iStartDown = l_iStartCur; 141 | } 142 | 143 | if( l_iStartUp == 0 || l_iStartUp < l_iStartCur ) { 144 | l_iStartUp = l_iStartCur; 145 | } 146 | 147 | if( l_iSeekDirection == 0 ) { 148 | l_iSeekDirection = 1; 149 | l_iStartCur = l_iStartDown - (l_iStartDown / 2); 150 | l_iReadCur = l_iStartDown - l_iStartCur; 151 | 152 | } else { 153 | l_iSeekDirection = 0; 154 | l_iReadCur = l_iRead / l_iSeekStep; 155 | l_iStartCur = l_iStartUp + l_iReadCur; 156 | } 157 | 158 | if( l_iStartCur < l_iStart) { 159 | l_iStartCur = l_iStart; 160 | l_iReadCur = l_iStartDown - l_iStartCur; 161 | } 162 | } 163 | */ 164 | 165 | fclose(l_pOutFile); 166 | 167 | if (m_pCodecCtx != NULL) { 168 | avcodec_close(m_pCodecCtx); 169 | avformat_close_input(&m_pFormatCtx); 170 | m_pCodecCtx = NULL; 171 | m_pFormatCtx = NULL; 172 | } 173 | 174 | // This is example that reads from end to start.. 175 | // 176 | //fe_decode_open(argv[1]); 177 | //fe_resample_open(m_pCodecCtx->sample_fmt, AV_SAMPLE_FMT_S16); 178 | // 179 | //l_pOutFile = fopen("out-rev.pcm", "w+"); 180 | // 181 | //for( i = l_iStart; i < l_iRead; i ++) { 182 | // memset(l_strBuffer, 0x33, 65355); 183 | // fwrite(l_strBuffer, 4608, 1, l_pOutFile); 184 | //} 185 | // 186 | // 187 | //for( i = l_iRead; i >= l_iStart; i --) { 188 | // memset(l_strBuffer, 0x00, 65355); 189 | // printf("Loop: %ld\n", i); 190 | // fe_read_seek(2304 * i); 191 | // l_iReadSize = fe_read_frame(l_strBuffer, 2304); 192 | // fseek( l_pOutFile, (2304 * 2) * (i - l_iStart), SEEK_SET); 193 | // fwrite(l_strBuffer, l_iReadSize, 1, l_pOutFile); 194 | // memset(l_strBuffer, 0x77, 65355); 195 | // // fwrite(l_strBuffer, 100, 1, l_pOutFile); 196 | //} 197 | // 198 | //fclose(l_pOutFile); 199 | 200 | if (m_pSwrCtx != NULL) { 201 | #ifndef __FFMPEGOLDAPI__ 202 | 203 | #ifdef __LIBAVRESAMPLE__ 204 | avresample_close(m_pSwrCtx); 205 | #else 206 | swr_free(&m_pSwrCtx); 207 | #endif 208 | 209 | #else 210 | audio_resample_close(m_pSwrCtx); 211 | #endif 212 | } 213 | 214 | return 0; 215 | } 216 | -------------------------------------------------------------------------------- /example2.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Tuukka Pasanen 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #include "example1.h" 22 | #include "example2.h" 23 | 24 | // AVCodecContext *m_pCodecCtx = NULL; 25 | enum AVSampleFormat m_pOutSampleFmt; 26 | enum AVSampleFormat m_pInSampleFmt; 27 | 28 | 29 | #ifndef __FFMPEGOLDAPI__ 30 | 31 | // Please choose to use libavresample.. people 32 | // Compile it now.. but because macports doesn't 33 | // Support both.. damn! 34 | #ifdef __LIBAVRESAMPLE__ 35 | AVAudioResampleContext *m_pSwrCtx = NULL; 36 | #else 37 | SwrContext *m_pSwrCtx = NULL; 38 | #endif 39 | uint8_t *m_pOut = NULL; 40 | #else 41 | ReSampleContext *m_pSwrCtx = NULL; 42 | short *m_pOut = NULL; 43 | #endif 44 | 45 | unsigned int m_pOutSize = -1; 46 | 47 | 48 | int fe_resample_open(enum AVSampleFormat inSampleFmt, 49 | enum AVSampleFormat outSampleFmt) { 50 | m_pOutSampleFmt = outSampleFmt; 51 | m_pInSampleFmt = inSampleFmt; 52 | 53 | 54 | // Some MP3/WAV don't tell this so make assumtion that 55 | // They are stereo not 5.1 56 | if (m_pCodecCtx->channel_layout == 0 && m_pCodecCtx->channels == 2) { 57 | m_pCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO; 58 | 59 | } else if (m_pCodecCtx->channel_layout == 0 && m_pCodecCtx->channels == 1) { 60 | m_pCodecCtx->channel_layout = AV_CH_LAYOUT_MONO; 61 | 62 | } else if (m_pCodecCtx->channel_layout == 0 && m_pCodecCtx->channels == 0) { 63 | m_pCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO; 64 | m_pCodecCtx->channels = 2; 65 | } 66 | 67 | printf("fe_resample_open: Rate: %d Channels %d Channels: %d\n", 68 | (int) m_pCodecCtx->sample_rate, 69 | (int) m_pCodecCtx->channel_layout, 70 | (int) m_pCodecCtx->channels); 71 | 72 | // They make big change in FFPEG 1.1 before that every format just passed 73 | // s16 back to application from FFMPEG 1.1 up MP3 pass s16p (Planar stereo 74 | // 16 bit) MP4/AAC FLTP (Planar 32 bit float) and OGG also FLTP 75 | // (WMA same thing) If sample type aint' S16 (Stero 16) example FFMPEG 1.1 76 | // mp3 is s16p that ain't and mp4 FLTP (32 bit float) 77 | // NOT Going to work because MIXXX works with pure s16 that is not planar 78 | // GOOD thing is now this can handle allmost everything.. 79 | // What should be tested is 44800 Hz downsample and 22100 Hz up sample. 80 | if ((inSampleFmt != outSampleFmt || m_pCodecCtx->sample_rate != 44100 || 81 | m_pCodecCtx->channel_layout != AV_CH_LAYOUT_STEREO) && m_pSwrCtx == NULL) { 82 | if (m_pSwrCtx != NULL) { 83 | printf("fe_resample_open: Freeing Resample context\n"); 84 | 85 | // __FFMPEGOLDAPI__ Is what is used in FFMPEG < 0.10 and libav < 0.8.3. NO 86 | // libresample available.. 87 | #ifndef __FFMPEGOLDAPI__ 88 | 89 | #ifdef __LIBAVRESAMPLE__ 90 | avresample_close(m_pSwrCtx); 91 | #else 92 | swr_free(&m_pSwrCtx); 93 | #endif 94 | 95 | #else 96 | audio_resample_close(m_pSwrCtx); 97 | #endif 98 | m_pSwrCtx = NULL; 99 | } 100 | 101 | // Create converter from in type to s16 sample rate 102 | #ifndef __FFMPEGOLDAPI__ 103 | 104 | #ifdef __LIBAVRESAMPLE__ 105 | printf("fe_resample_open: ffmpeg: NEW FFMPEG API using libavresample\n"); 106 | m_pSwrCtx = avresample_alloc_context(); 107 | #else 108 | printf("fe_resample_open: ffmpeg: NEW FFMPEG API using libswresample\n"); 109 | m_pSwrCtx = swr_alloc(); 110 | #endif 111 | 112 | av_opt_set_int(m_pSwrCtx, "in_channel_layout", m_pCodecCtx->channel_layout, 0); 113 | av_opt_set_int(m_pSwrCtx, "in_sample_fmt", inSampleFmt, 0); 114 | av_opt_set_int(m_pSwrCtx, "in_sample_rate", m_pCodecCtx->sample_rate, 0); 115 | av_opt_set_int(m_pSwrCtx, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); 116 | av_opt_set_int(m_pSwrCtx, "out_sample_fmt", outSampleFmt, 0); 117 | av_opt_set_int(m_pSwrCtx, "out_sample_rate", m_pCodecCtx->sample_rate, 0); 118 | 119 | #else 120 | printf("fe_resample_open: ffmpeg: OLD FFMPEG API in use!\n"); 121 | m_pSwrCtx = av_audio_resample_init(2, 122 | m_pCodecCtx->channels, 123 | m_pCodecCtx->sample_rate, 124 | m_pCodecCtx->sample_rate, 125 | outSampleFmt, 126 | inSampleFmt, 127 | 16, 128 | 10, 129 | 0, 130 | 0.8); 131 | 132 | #endif 133 | 134 | if (!m_pSwrCtx) { 135 | printf("fe_resample_open: Can't init convertor!\n"); 136 | return -1; 137 | } 138 | 139 | #ifndef __FFMPEGOLDAPI__ 140 | // If it not working let user know about it! 141 | // If we don't do this we'll gonna crash 142 | #ifdef __LIBAVRESAMPLE__ 143 | 144 | if (avresample_open(m_pSwrCtx) < 0) { 145 | #else 146 | 147 | if (swr_init(m_pSwrCtx) < 0) { 148 | #endif 149 | printf("fe_resample_open: Can't init convertor\n"); 150 | m_pSwrCtx = NULL; 151 | return -1; 152 | } 153 | 154 | #endif 155 | 156 | } 157 | 158 | // If we have FFMpeg version which is less than 3.2 then we use older implementation 159 | #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 0) 160 | printf("fe_resample_open: From Sample: %d Hz Sample format: %s", 161 | m_pFormatCtx->streams[m_iAudioStream]->codec->sample_rate, 162 | av_get_sample_fmt_name(inSampleFmt)); 163 | #else 164 | printf("fe_resample_open: From Sample: %d Hz Sample format: %s", 165 | m_pFormatCtx->streams[m_iAudioStream]->codecpar->sample_rate, 166 | av_get_sample_fmt_name(inSampleFmt)); 167 | #endif 168 | 169 | printf(" to 44100 Sample format: %s\n", 170 | av_get_sample_fmt_name(outSampleFmt)); 171 | 172 | return 0; 173 | } 174 | 175 | unsigned int fe_resample_do(AVFrame *inframe) { 176 | 177 | if (m_pSwrCtx) { 178 | 179 | #ifndef __FFMPEGOLDAPI__ 180 | 181 | #ifdef __LIBAVRESAMPLE__ 182 | #if LIBAVRESAMPLE_VERSION_MAJOR == 0 183 | void **l_pIn = (void **)inframe->extended_data; 184 | #else 185 | uint8_t **l_pIn = (uint8_t **)inframe->extended_data; 186 | #endif 187 | #else 188 | uint8_t **l_pIn = (uint8_t **)inframe->extended_data; 189 | #endif 190 | 191 | // Left here for reason! 192 | // Sometime in time we will need this! 193 | //#else 194 | // int64_t l_lInReadBytes = av_samples_get_buffer_size(NULL, m_pCodecCtx->channels, 195 | // inframe->nb_samples, 196 | // m_pCodecCtx->sample_fmt, 1); 197 | #endif 198 | 199 | #ifndef __FFMPEGOLDAPI__ 200 | int l_iOutBytes = 0; 201 | 202 | #if __LIBAVRESAMPLE__ 203 | int l_iOutSamples = av_rescale_rnd(avresample_get_delay(m_pSwrCtx) + 204 | inframe->nb_samples, 205 | m_pCodecCtx->sample_rate, 206 | m_pCodecCtx->sample_rate, 207 | AV_ROUND_UP); 208 | #else 209 | int l_iOutSamples = av_rescale_rnd(swr_get_delay(m_pSwrCtx, 210 | m_pCodecCtx->sample_rate) + 211 | inframe->nb_samples, 212 | m_pCodecCtx->sample_rate, 213 | m_pCodecCtx->sample_rate, 214 | AV_ROUND_UP); 215 | #endif 216 | int l_iOutSamplesLines = 0; 217 | 218 | // Alloc too much.. if not enough we are in trouble! 219 | if( av_samples_alloc(&m_pOut, &l_iOutSamplesLines, 2, l_iOutSamples, 220 | m_pOutSampleFmt, 1) < 0 ) { 221 | printf("fe_resample_do: Alloc not succeedeed\n"); 222 | return -1; 223 | } 224 | 225 | #else 226 | int l_iOutSamples = av_rescale_rnd(inframe->nb_samples, 227 | m_pCodecCtx->sample_rate, 228 | m_pCodecCtx->sample_rate, 229 | AV_ROUND_UP); 230 | 231 | int l_iOutBytes = av_samples_get_buffer_size(NULL, 2, 232 | l_iOutSamples, 233 | m_pOutSampleFmt, 1); 234 | 235 | 236 | m_pOut = (short *)malloc(l_iOutBytes * 2); 237 | #endif 238 | 239 | int l_iLen = 0; 240 | #ifndef __FFMPEGOLDAPI__ 241 | 242 | #ifdef __LIBAVRESAMPLE__ 243 | 244 | // OLD API (0.0.3) ... still NEW API (1.0.0 and above).. very frustrating.. 245 | // USED IN FFMPEG 1.0 (LibAV SOMETHING!). New in FFMPEG 1.1 and libav 9 246 | #if LIBAVRESAMPLE_VERSION_INT <= 3 247 | // AVResample OLD 248 | l_iLen = avresample_convert(m_pSwrCtx, (void **)&m_pOut, 0, l_iOutSamples, 249 | (void **)l_pIn, 0, inframe->nb_samples); 250 | #else 251 | //AVResample NEW 252 | l_iLen = avresample_convert(m_pSwrCtx, (uint8_t **)&m_pOut, 0, l_iOutSamples, 253 | (uint8_t **)l_pIn, 0, inframe->nb_samples); 254 | 255 | #endif 256 | 257 | #else 258 | 259 | // SWResample 260 | l_iLen = swr_convert(m_pSwrCtx, (uint8_t **)&m_pOut, l_iOutSamples, 261 | (const uint8_t **)l_pIn, inframe->nb_samples); 262 | 263 | 264 | #endif 265 | 266 | l_iOutBytes = av_samples_get_buffer_size(NULL, 2, l_iLen, m_pOutSampleFmt, 1); 267 | 268 | #else 269 | l_iLen = audio_resample(m_pSwrCtx, 270 | (short *)m_pOut, (short *)inframe->data[0], 271 | inframe->nb_samples); 272 | 273 | #endif 274 | 275 | if (l_iLen < 0) { 276 | printf("Sample format conversion failed!\n"); 277 | return -1; 278 | } 279 | 280 | m_pOutSize = l_iOutBytes; 281 | return l_iOutBytes; 282 | 283 | } else { 284 | return 0; 285 | } 286 | 287 | return 0; 288 | } 289 | -------------------------------------------------------------------------------- /example4.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Tuukka Pasanen 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #include "example1.h" 22 | #include "example2.h" 23 | #include "example3.h" 24 | #include "example4.h" 25 | 26 | int64_t m_iSeekOffset = -1; 27 | int64_t m_iLastFirstFfmpegByteOffset = -1; 28 | int64_t m_iCurrentTs = -1; 29 | int64_t m_iOffset = -1; 30 | int m_bIsSeeked = 0; 31 | 32 | long fe_read_seek(long filepos) { 33 | int ret = 0; 34 | int64_t fspos = 0; 35 | int64_t l_lSeekPos = 0; 36 | int64_t minus = filepos; 37 | AVRational time_base = m_pFormatCtx->streams[m_iAudioStream]->time_base; 38 | 39 | minus = (int64_t)((double)filepos / 2304); 40 | minus *= 2304; 41 | 42 | if( minus >= (2304 * 4) ) { 43 | minus -= (2304 * 4); 44 | 45 | } else { 46 | minus = 0; 47 | } 48 | 49 | fspos = (int64_t) round(fe_convert_fromByteOffset((double)minus, 44100, &time_base)); 50 | m_iCurrentTs = filepos; 51 | 52 | m_iOffset = 0; 53 | 54 | avcodec_flush_buffers(m_pCodecCtx); 55 | 56 | ret = avformat_seek_file(m_pFormatCtx, 57 | m_iAudioStream, 58 | 0, 59 | fspos, 60 | fspos, 61 | AVSEEK_FLAG_BACKWARD); 62 | 63 | 64 | avcodec_flush_buffers(m_pCodecCtx); 65 | 66 | if (ret < 0) { 67 | printf("fe_read_seek: Seek ERROR ret(%d) filepos(%ld)\n", 68 | ret, 69 | filepos); 70 | return 0; 71 | } 72 | 73 | l_lSeekPos = (int64_t) round(fe_convert_toByteOffset( 74 | m_pFormatCtx->streams[m_iAudioStream]->cur_dts, 44100, &time_base)); 75 | 76 | m_iLastFirstFfmpegByteOffset = l_lSeekPos; 77 | 78 | 79 | m_iSeekOffset = m_iOffset = (int64_t) round(fe_convert_toByteOffset((double)(fspos - m_pFormatCtx->streams[m_iAudioStream]->cur_dts), 80 | 44100, &time_base)); 81 | 82 | m_iSeekOffset = (int64_t) round((double)l_lSeekPos / 2304); 83 | m_iSeekOffset *= 2304; 84 | 85 | printf("fe_read_seek: (RBP: %ld/%.4f) Req Byte: %ld (Sec: %.4f PTS %ld) Real PTS %ld (Sec: %.4f Byte: %ld)\n", 86 | filepos, 87 | (double)((double)filepos / (double)88200), 88 | minus, 89 | (double)((double)minus / (double)88200), 90 | fspos, 91 | m_pFormatCtx->streams[m_iAudioStream]->cur_dts, m_pFormatCtx->streams[m_iAudioStream]->cur_dts * av_q2d(m_pFormatCtx->streams[m_iAudioStream]->time_base), 92 | (int64_t) round(fe_convert_toByteOffset((double)m_pFormatCtx->streams[m_iAudioStream]->cur_dts, 44100, &time_base))); 93 | 94 | m_bIsSeeked = 1; 95 | 96 | return filepos; 97 | } 98 | 99 | 100 | unsigned int fe_read_frame(char *buffer, int size) { 101 | AVPacket l_SPacket; 102 | #if LIBAVCODEC_VERSION_INT >= 3616100 103 | AVFrame *l_pFrame = av_frame_alloc(); 104 | #else 105 | AVFrame *l_pFrame = avcodec_alloc_frame(); 106 | #endif 107 | int l_iCopySize = size * 2; 108 | 109 | int m_bReadLoop = 0; 110 | int l_iReadBytes = 0; 111 | 112 | double l_fCurrentFFMPEGPosSec = 0; 113 | double l_fCurrentFFMPEGPosByte = 0; 114 | 115 | int ret = 0; 116 | int64_t l_iOffset = 0; 117 | int64_t l_iReadedBytes = 0; 118 | int64_t l_iCopiedBytes = 0; 119 | 120 | // Just make sure everything is zeroed before use 121 | // Needless but.. 122 | memset(buffer, 0x00, size); 123 | 124 | l_SPacket.data = NULL; 125 | l_SPacket.size = 0; 126 | av_init_packet(&l_SPacket); 127 | 128 | //while (readByteArray.size() < needed) 129 | while (!m_bReadLoop) { 130 | if (av_read_frame(m_pFormatCtx, &l_SPacket) >= 0) { 131 | if (l_SPacket.stream_index == m_iAudioStream) { 132 | 133 | // If we have FFMpeg version which is less than 3.2 then we use older implementation 134 | #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 0) 135 | ret = avcodec_decode_audio4(m_pCodecCtx, l_pFrame, &l_iFrameFinished, &l_SPacket); 136 | 137 | if (ret <= 0) { 138 | #else 139 | 140 | // AVERROR(EAGAIN) means that we need to feed more 141 | // That we can decode Frame or Packet 142 | do { 143 | do { 144 | ret = avcodec_send_packet(m_pCodecCtx, &l_SPacket); 145 | } while(ret == AVERROR(EAGAIN)); 146 | 147 | if(ret == AVERROR_EOF || ret == AVERROR(EINVAL)) { 148 | printf("AVERROR(EAGAIN): %d, AVERROR_EOF: %d, AVERROR(EINVAL): %d\n", AVERROR(EAGAIN), AVERROR_EOF, AVERROR(EINVAL)); 149 | printf("fe_read_frame: Frame getting error (%d)!\n", ret); 150 | return 0; 151 | } 152 | 153 | ret = avcodec_receive_frame(m_pCodecCtx, l_pFrame); 154 | } while(ret == AVERROR(EAGAIN)); 155 | 156 | if(ret == AVERROR_EOF || ret == AVERROR(EINVAL)) { 157 | #endif 158 | 159 | // An error or EOF occured,index break out and return what 160 | // we have so far. 161 | printf("AVERROR(EAGAIN): %d, AVERROR_EOF: %d, AVERROR(EINVAL): %d\n", AVERROR(EAGAIN), AVERROR_EOF, AVERROR(EINVAL)); 162 | printf("fe_read_frame: EOF or some othere decoding error (%d)!\n", ret); 163 | return 0; 164 | } 165 | 166 | // If we have FFMpeg version which is less than 3.2 then we use older implementation 167 | #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 0) 168 | 169 | //frame-> 170 | if (l_iFrameFinished) { 171 | #endif 172 | fe_resample_do(l_pFrame); 173 | l_iReadBytes = av_samples_get_buffer_size(NULL, m_pCodecCtx->channels, 174 | l_pFrame->nb_samples, 175 | m_pCodecCtx->sample_fmt, 1); 176 | 177 | l_fCurrentFFMPEGPosSec = l_SPacket.pts * av_q2d(m_pFormatCtx->streams[m_iAudioStream]->time_base); 178 | 179 | l_fCurrentFFMPEGPosByte = fe_convert_toByteOffset((double)l_SPacket.pts, 44100, 180 | &m_pFormatCtx->streams[m_iAudioStream]->time_base); 181 | 182 | 183 | if( m_iCurrentTs > l_fCurrentFFMPEGPosByte && l_iOffset == 0) { 184 | l_iOffset = m_iCurrentTs - (int64_t) round(l_fCurrentFFMPEGPosByte); 185 | printf("fe_read_frame: Offset %ld = %ld - %ld\n", 186 | l_iOffset, 187 | m_iCurrentTs, 188 | (int64_t) round(l_fCurrentFFMPEGPosByte)); 189 | l_iOffset *= 2; 190 | } 191 | 192 | if( l_iOffset >= l_iReadBytes && m_pOut == NULL) { 193 | l_iOffset -= l_iReadBytes; 194 | printf("fe_read_frame: Offset left/readed: %ld/%ld (was: %ld) (PTS: %ld/%ld)\n", 195 | l_iOffset, 196 | (long int)l_iReadBytes, 197 | (l_iOffset + l_iReadBytes), 198 | (long int)l_SPacket.pts, 199 | (int64_t) round(l_fCurrentFFMPEGPosByte)); 200 | continue; 201 | 202 | } else if( l_iOffset >= m_pOutSize) { 203 | l_iOffset -= m_pOutSize; 204 | printf("fe_read_frame: Resample Offset left/readed: %ld/%ld (was: %ld) (PTS: %ld/%ld)\n", 205 | l_iOffset, 206 | (long int) m_pOutSize, 207 | (long int) (l_iOffset + m_pOutSize), 208 | (long int) l_SPacket.pts, 209 | (long int) round(l_fCurrentFFMPEGPosByte)); 210 | continue; 211 | } 212 | 213 | printf("fe_read_frame: Cur Sec %.4f (Byte: %ld) Got bytes: (%d @ PTS %ld) (buffered: %ld/%ld)\n", 214 | l_fCurrentFFMPEGPosSec, 215 | (long int) round(l_fCurrentFFMPEGPosByte), 216 | l_iReadBytes, 217 | (long int) l_SPacket.pts, 218 | (long int) l_iReadedBytes, 219 | (long int) l_iCopySize); 220 | 221 | l_iReadedBytes += (l_iReadBytes / 2); 222 | 223 | if( m_pOut != NULL ) { 224 | 225 | if( (m_pOutSize - l_iOffset) < l_iCopySize ) { 226 | printf("fe_read_frame: Resampled Copy Size: %ld Readed: %ld Offset: %ld Copied: %ld\n", 227 | (long int)l_iCopySize, 228 | (long int)m_pOutSize, 229 | (long int)l_iOffset, 230 | (long int)(m_pOutSize - l_iOffset)); 231 | memcpy(buffer, m_pOut + l_iOffset, (m_pOutSize - l_iOffset)); 232 | buffer += (m_pOutSize - l_iOffset); 233 | l_iCopiedBytes += (m_pOutSize - l_iOffset); 234 | 235 | } else { 236 | printf("fe_read_frame: Resampled Last Copy Size: %ld Readed: %ld Offset: %ld\n", 237 | (long int)l_iCopySize, 238 | (long int)m_pOutSize, 239 | (long int)l_iOffset); 240 | memcpy(buffer, m_pOut, l_iCopySize); 241 | l_iCopiedBytes += l_iCopySize; 242 | } 243 | 244 | l_iCopySize -= m_pOutSize - l_iOffset; 245 | m_pOutSize = 0; 246 | free(m_pOut); 247 | m_pOut = NULL; 248 | 249 | } else { 250 | if( (l_iReadBytes - l_iOffset) < l_iCopySize ) { 251 | printf("fe_read_frame: Copy Size: %ld Readed: %ld Offset: %ld Copied: %ld\n", 252 | (long int)l_iCopySize, 253 | (long int)l_iReadBytes, 254 | (long int)l_iOffset, 255 | (long int)(l_iReadBytes - l_iOffset)); 256 | memcpy(buffer, l_pFrame->data[0] + l_iOffset, (l_iReadBytes - l_iOffset)); 257 | buffer += (l_iReadBytes - l_iOffset); 258 | l_iCopiedBytes += (l_iReadBytes - l_iOffset); 259 | 260 | } else { 261 | printf("fe_read_frame: Last Copy Size: %ld Readed: %ld Offset: %ld\n", 262 | (long int)l_iCopySize, 263 | (long int)l_iReadBytes, 264 | (long int)l_iOffset); 265 | memcpy(buffer, l_pFrame->data[0], l_iCopySize); 266 | l_iCopiedBytes += l_iCopySize; 267 | } 268 | 269 | l_iCopySize -= l_iReadBytes - l_iOffset; 270 | } 271 | 272 | l_iOffset = 0; 273 | 274 | if( l_iCopySize <= 0) { 275 | m_bReadLoop = 1; 276 | } 277 | 278 | // If we have FFMpeg version which is less than 3.2 then we use older implementation 279 | #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 0) 280 | 281 | } else { 282 | printf("fe_read_frame: libavcodec 'avcodec_decode_audio4' didn't succeed or frame not finished (File could also just end!)\n"); 283 | } 284 | 285 | #endif 286 | } 287 | 288 | } else { 289 | printf("fe_read_frame: libavcodec 'av_read_frame' didn't succeed!\n"); 290 | //break; 291 | } 292 | 293 | // If we have FFMpeg version which is less than 3.2 then we use older implementation 294 | #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 0) 295 | av_free_packet(&l_SPacket); 296 | #else 297 | av_packet_unref(&l_SPacket); 298 | #endif 299 | l_SPacket.data = NULL; 300 | l_SPacket.size = 0; 301 | av_init_packet(&l_SPacket); 302 | 303 | } 304 | 305 | av_free( l_SPacket.data ); 306 | l_SPacket.data = NULL; 307 | l_SPacket.size = 0; 308 | 309 | #if LIBAVFORMAT_VERSION_INT < 3613028 310 | avcodec_get_frame_defaults(l_pFrame); 311 | #else 312 | av_frame_unref(l_pFrame); 313 | #endif 314 | 315 | printf("fe_read_frame: Readed bytes %ld Copied bytes: %ld\n", l_iReadedBytes, l_iCopiedBytes); 316 | return l_iCopiedBytes; 317 | } 318 | 319 | --------------------------------------------------------------------------------