diff options
-rw-r--r--[-rwxr-xr-x] | media/base/media_posix.cc | 214 | ||||
-rw-r--r--[-rwxr-xr-x] | media/base/media_win.cc | 4 | ||||
-rw-r--r-- | media/bench/bench.cc | 11 | ||||
-rw-r--r-- | media/media.gyp | 53 |
4 files changed, 248 insertions, 34 deletions
diff --git a/media/base/media_posix.cc b/media/base/media_posix.cc index 664f9f8..331a143 100755..100644 --- a/media/base/media_posix.cc +++ b/media/base/media_posix.cc @@ -4,15 +4,227 @@ #include "media/base/media.h" +#include <string> + +#include <dlfcn.h> + +#include "base/file_path.h" #include "base/logging.h" #include "base/path_service.h" +#include "media/filters/ffmpeg_common.h" + +// We create stub references to dynamically loaded functions in ffmpeg +// for ease of linking. +// +// TODO(ajwong): We need to find a more maintainable way to have this work. +// Also, this code should really be in the ffmpeg wrapper, and not here +// in the media level. The concept of "weak symbols" looks like it might +// be promising, but I don't quite understand it yet. +extern "C" { + +void (*avcodec_init_ptr)(void) = NULL; +void avcodec_init(void) { + avcodec_init_ptr(); +} + +AVCodec* (*avcodec_find_decoder_ptr)(enum CodecID id) = NULL; +AVCodec* avcodec_find_decoder(enum CodecID id) { + return avcodec_find_decoder_ptr(id); +} + +int (*avcodec_thread_init_ptr)(AVCodecContext* s, int thread_count) = NULL; +int avcodec_thread_init(AVCodecContext* s, int thread_count) { + return avcodec_thread_init_ptr(s, thread_count); +} + +int (*avcodec_open_ptr)(AVCodecContext* avctx, AVCodec* codec) = NULL; +int avcodec_open(AVCodecContext* avctx, AVCodec* codec) { + return avcodec_open_ptr(avctx, codec); +} + +AVFrame* (*avcodec_alloc_frame_ptr)(void) = NULL; +AVFrame* avcodec_alloc_frame(void) { + return avcodec_alloc_frame_ptr(); +} + +int (*avcodec_decode_audio2_ptr)(AVCodecContext* avctx, int16_t* samples, + int* frame_size_ptr, const uint8_t* buf, + int buf_size) = NULL; +int avcodec_decode_audio2(AVCodecContext* avctx, int16_t* samples, + int* frame_size_ptr, + const uint8_t* buf, int buf_size) { + + return avcodec_decode_audio2_ptr(avctx, samples, frame_size_ptr, buf, + buf_size); +} + + +int (*avcodec_decode_video_ptr)(AVCodecContext* avctx, AVFrame* picture, + int* got_picture_ptr, const uint8_t* buf, + int buf_size) = NULL; +int avcodec_decode_video(AVCodecContext* avctx, AVFrame* picture, + int* got_picture_ptr, const uint8_t* buf, + int buf_size) { + return avcodec_decode_video_ptr(avctx, picture, got_picture_ptr, buf, + buf_size); +} + + +void (*av_register_all_ptr)(void); +void av_register_all(void) { + av_register_all_ptr(); +} + +int (*av_open_input_file_ptr)(AVFormatContext** ic_ptr, const char* filename, + AVInputFormat* fmt, int buf_size, + AVFormatParameters* ap) = NULL; +int av_open_input_file(AVFormatContext** ic_ptr, const char* filename, + AVInputFormat* fmt, int buf_size, + AVFormatParameters* ap) { + return av_open_input_file_ptr(ic_ptr, filename, fmt, buf_size, ap); +} + +int (*av_find_stream_info_ptr)(AVFormatContext* ic) = NULL; +int av_find_stream_info(AVFormatContext* ic) { + return av_find_stream_info_ptr(ic); +} + +int (*av_read_frame_ptr)(AVFormatContext* s, AVPacket* pkt) = NULL; +int av_read_frame(AVFormatContext* s, AVPacket* pkt) { + return av_read_frame_ptr(s, pkt); +} + + +void* (*av_malloc_ptr)(unsigned int size) = NULL; +void* av_malloc(unsigned int size) { + return av_malloc_ptr(size); +} + +} // extern "C" + namespace media { +namespace { + +enum FFmpegDSOKeys { + FILE_LIBAVCODEC, // full path to libavcodec media decoding library. + FILE_LIBAVFORMAT, // full path to libavformat media parsing library. + FILE_LIBAVUTIL, // full path to libavutil media utility library. +}; + +// Retrieves the DLLName for the given key. +std::string GetDSOName(FFmpegDSOKeys dso_key) { + // TODO(ajwong): Do we want to lock to a specific ffmpeg version? + // TODO(port): These library names are incorrect for mac. We need .dynlib + // suffixes. + switch (dso_key) { + case FILE_LIBAVCODEC: + return FILE_PATH_LITERAL("libavcodec.so.52"); + case FILE_LIBAVFORMAT: + return FILE_PATH_LITERAL("libavformat.so.52"); + case FILE_LIBAVUTIL: + return FILE_PATH_LITERAL("libavutil.so.50"); + default: + LOG(DFATAL) << "Invalid DSO key requested: " << dso_key; + return FILE_PATH_LITERAL(""); + } +} + +} // namespace + // Attempts to initialize the media library (loading DLLs, DSOs, etc.). // Returns true if everything was successfully initialized, false otherwise. bool InitializeMediaLibrary(const FilePath& module_dir) { - NOTIMPLEMENTED(); + // TODO(ajwong): We need error resolution. + FFmpegDSOKeys path_keys[] = { + FILE_LIBAVCODEC, + FILE_LIBAVFORMAT, + FILE_LIBAVUTIL + }; + void* libs[arraysize(path_keys)] = {}; + for (size_t i = 0; i < arraysize(path_keys); ++i) { + FilePath path = module_dir.Append(GetDSOName(path_keys[i])); + libs[i] = dlopen(path.value().c_str(), RTLD_LAZY); + if (!libs[i]) + break; + } + + // Check that we loaded all libraries successfully. We only need to check the + // last array element because the loop above breaks on any failure. + if (libs[arraysize(libs)-1] == NULL) { + // Free any loaded libraries if we weren't successful. + for (size_t i = 0; i < arraysize(libs) && libs[i] != NULL; ++i) { + dlclose(libs[i]); + libs[i] = NULL; // Just to be safe. + } + return false; + } + + // TODO(ajwong): Extract this to somewhere saner, and hopefully + // autogenerate the bindings from the .def files. Having all this + // code here is incredibly ugly. + avcodec_init_ptr = + reinterpret_cast<void(*)(void)>( + dlsym(libs[FILE_LIBAVCODEC], "avcodec_init")); + avcodec_find_decoder_ptr = + reinterpret_cast<AVCodec* (*)(enum CodecID)>( + dlsym(libs[FILE_LIBAVCODEC], "avcodec_find_decoder")); + avcodec_thread_init_ptr = + reinterpret_cast<int (*)(AVCodecContext*, int)>( + dlsym(libs[FILE_LIBAVCODEC], "avcodec_thread_init")); + avcodec_open_ptr = + reinterpret_cast<int (*)(AVCodecContext*, AVCodec*)>( + dlsym(libs[FILE_LIBAVCODEC], "avcodec_open")); + avcodec_alloc_frame_ptr = + reinterpret_cast<AVFrame* (*)(void)>( + dlsym(libs[FILE_LIBAVCODEC], "avcodec_alloc_frame")); + avcodec_decode_audio2_ptr = + reinterpret_cast<int (*)(AVCodecContext*, int16_t*, int*, + const uint8_t*, int)>( + dlsym(libs[FILE_LIBAVCODEC], "avcodec_decode_audio2")); + avcodec_decode_video_ptr = + reinterpret_cast<int (*)(AVCodecContext*, AVFrame*, int*, + const uint8_t*, int)>( + dlsym(libs[FILE_LIBAVCODEC], "avcodec_decode_video")); + + av_register_all_ptr = + reinterpret_cast<void(*)(void)>( + dlsym(libs[FILE_LIBAVFORMAT], "av_register_all")); + av_open_input_file_ptr = + reinterpret_cast<int (*)(AVFormatContext**, const char*, + AVInputFormat*, int, + AVFormatParameters*)>( + dlsym(libs[FILE_LIBAVFORMAT], "av_open_input_file")); + av_find_stream_info_ptr = + reinterpret_cast<int (*)(AVFormatContext*)>( + dlsym(libs[FILE_LIBAVFORMAT], "av_find_stream_info")); + av_read_frame_ptr = + reinterpret_cast<int (*)(AVFormatContext*, AVPacket*)>( + dlsym(libs[FILE_LIBAVFORMAT], "av_read_frame")); + + av_malloc_ptr = + reinterpret_cast<void* (*)(unsigned int)>( + dlsym(libs[FILE_LIBAVUTIL], "av_malloc")); + + // Check that all the symbols were loaded correctly before returning true. + if (avcodec_init_ptr && + avcodec_find_decoder_ptr && + avcodec_thread_init_ptr && + avcodec_open_ptr && + avcodec_alloc_frame_ptr && + avcodec_decode_audio2_ptr && + avcodec_decode_video_ptr && + + av_register_all_ptr && + av_open_input_file_ptr && + av_find_stream_info_ptr && + av_read_frame_ptr && + + av_malloc_ptr) { + return true; + } + return false; } diff --git a/media/base/media_win.cc b/media/base/media_win.cc index c0219d9..aa006a4 100755..100644 --- a/media/base/media_win.cc +++ b/media/base/media_win.cc @@ -54,7 +54,9 @@ bool InitializeMediaLibrary(const FilePath& base_path) { break; } - // Check that we loaded all libraries successfully. + // Check that we loaded all libraries successfully. We only need to check the + // last array element because the loop above will break without initializing + // it on any prior error. if (libs[arraysize(libs)-1]) return true; diff --git a/media/bench/bench.cc b/media/bench/bench.cc index 9e8f032..3494600 100644 --- a/media/bench/bench.cc +++ b/media/bench/bench.cc @@ -7,16 +7,18 @@ // options. We also use this tool to measure performance regressions when // testing newer builds of FFmpeg from trunk. -#include <windows.h> #include <iomanip> #include <iostream> +#include <string> #include "base/at_exit.h" #include "base/basictypes.h" #include "base/command_line.h" +#include "base/file_path.h" #include "base/logging.h" #include "base/string_util.h" #include "base/time.h" +#include "media/base/media.h" #include "media/filters/ffmpeg_common.h" namespace switches { @@ -46,6 +48,8 @@ int main(int argc, const char** argv) { return 1; } + media::InitializeMediaLibrary(FilePath()); + // Retrieve command line options. std::string path(WideToUTF8(filenames[0])); CodecType target_codec = CODEC_TYPE_UNKNOWN; @@ -66,7 +70,8 @@ int main(int argc, const char** argv) { // Determine number of threads to use for video decoding (optional). std::wstring threads(cmd_line->GetSwitchValue(switches::kVideoThreads)); - if (!threads.empty() && !StringToInt(threads, &video_threads)) { + if (!threads.empty() && + !StringToInt(WideToUTF16Hack(threads), &video_threads)) { video_threads = 0; } @@ -78,7 +83,7 @@ int main(int argc, const char** argv) { int skip = 0; if (cmd_line->HasSwitch(switches::kSkip)) { std::wstring skip_opt(cmd_line->GetSwitchValue(switches::kSkip)); - if (!StringToInt(skip_opt, &skip)) { + if (!StringToInt(WideToUTF16Hack(skip_opt), &skip)) { skip = 0; } } diff --git a/media/media.gyp b/media/media.gyp index d5c2323..7f144d1 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -176,35 +176,30 @@ }], ], }, - ], - 'conditions': [ - ['OS=="win"', { - 'targets': [ - { - 'target_name': 'media_player', - 'type': 'executable', - 'dependencies': [ - 'media', - '../base/base.gyp:base', - '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg', - ], - 'sources': [ - ], - }, - { - 'target_name': 'media_bench', - 'type': 'executable', - 'msvs_guid': '45BC4F87-4604-4962-A751-7C7B29A080BF', - 'dependencies': [ - 'media', - '../base/base.gyp:base', - '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg', - ], - 'sources': [ - 'bench/bench.cc', - ], - }, + { + 'target_name': 'media_player', + 'type': 'executable', + 'dependencies': [ + 'media', + '../base/base.gyp:base', + '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg', ], - }], + 'sources': [ + 'player/player.cc', + ], + }, + { + 'target_name': 'media_bench', + 'type': 'executable', + 'msvs_guid': '45BC4F87-4604-4962-A751-7C7B29A080BF', + 'dependencies': [ + 'media', + '../base/base.gyp:base', + '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg', + ], + 'sources': [ + 'bench/bench.cc', + ], + }, ], } |