xref: /MusicPlayer2/MusicPlayer2/FfmpegCore.cpp (revision 8959a120c2c1a8b30f887255062f37449f37dee8)
1 #include "stdafx.h"
2 #include "FfmpegCore.h"
3 
4 #include "AudioCommon.h"
5 #include "Common.h"
6 #include "MusicPlayer2.h"
7 #include "Player.h"
8 
9 #define ft2ts(t) (((size_t)t.dwHighDateTime << 32) | (size_t)t.dwLowDateTime)
10 
11 static std::wstring last_ffmpeg_core_error_cache;
12 
CFfmpegCore()13 CFfmpegCore::CFfmpegCore() {
14     handle = nullptr;
15     err = 0;
16     Init(L"ffmpeg_core.dll");
17     if (!IsSucceed()) {
18         const wstring& info = theApp.m_str_table.LoadText(L"LOG_FFMPEG_INIT_FAILED");
19         theApp.WriteLog(info);
20     }
21 }
22 
~CFfmpegCore()23 CFfmpegCore::~CFfmpegCore() {
24     if (handle || settings) UnInitCore();
25     CDllLib::UnInit();
26 }
27 
InitCore()28 void CFfmpegCore::InitCore() {
29     if (IsSucceed()) {
30         CAudioCommon::m_surpported_format.clear();
31         CAudioCommon::m_all_surpported_extensions.clear();
32         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"mp3 wma wav m4a ogg oga flac ape mp2 mp1 opus ape cda aif aiff cue mp4 mkv mka m2ts", theApp.m_str_table.LoadText(L"TXT_FILE_TYPE_BASE").c_str()));
33         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"3gp 3g2 mj2 psp m4b ism ismv isma f4v", L"3gp"));
34         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"aa", L"Audible Format 2, 3, and 4"));
35         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"aac", L"AAC (Advanced Audio Coding)"));
36         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"ac3", L"ATSC A/52A (AC-3)"));
37         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"alac", L"ALAC (Apple Lossless Audio Codec)"));
38         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"asf", L"Advanced Systems Format"));
39         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"als", L"MPEG-4 Audio Lossless Coding (ALS)"));
40         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"amr", L"AMR"));
41         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"ape mac", L"Monkey's Audio"));
42         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"aptx", L"aptX (Audio Processing Technology for Bluetooth)"));
43         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"atrac", L"Adaptive TRansform Acoustic Coding"));
44         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"dst", L"DST (Digital Stream Transfer)"));
45         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"dca", L"DCA (DTS Coherent Acoustics)"));
46         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"flac fla", L"FLAC (Free Lossless Audio Codec)"));
47         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"flv live_flv kux", L"Adobe Flash Video"));
48         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"gsm", L"GSM"));
49         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"mp1 mp2 mp3 mp4", L"MPEG audio"));
50         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"m4a mp4", L"MP4"));
51         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"opus", L"Opus"));
52         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"pcm", L"PCM"));
53         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"spx", L"Speex"));
54         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"tak", L"TAK (Tom's lossless Audio Kompressor)"));
55         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"tta", L"TTA (True Audio)"));
56         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"ogg oga", L"Vorbis"));
57         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"wv", L"WavPack"));
58         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"mpc mp+ mpp", L"Musepack"));
59         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"wma", L"Windows Media Audio"));
60         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"mov", L"mov"));
61         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"avi", L"Audio Video Interleaved"));
62         CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(L"cda", L"CD Audio"));
63 
64         if (!theApp.m_nc_setting_data.user_defined_type_ffmpeg.empty())
65         {
66             CAudioCommon::m_surpported_format.push_back(CAudioCommon::CreateSupportedFormat(theApp.m_nc_setting_data.user_defined_type_ffmpeg, theApp.m_str_table.LoadText(L"TXT_FILE_TYPE_FFMPEG_USER_DEFINE").c_str()));
67         }
68 
69         for (const auto& item : CAudioCommon::m_surpported_format)
70         {
71             for (const auto& ext : item.extensions)
72             {
73                 if (!ext.empty() && !CCommon::IsItemInVector(CAudioCommon::m_all_surpported_extensions, ext))
74                     CAudioCommon::m_all_surpported_extensions.push_back(ext);
75             }
76         }
77 
78         settings = ffmpeg_core_init_settings();
79         ffmpeg_core_log_set_flags(AV_LOG_SKIP_REPEATED | AV_LOG_PRINT_LEVEL);
80         ffmpeg_core_log_set_callback(LogCallback);
81         UpdateSettings();
82         auto devices = GetAudioDevices();
83         DeviceInfo d;
84         d.index = -1;
85         d.name = theApp.m_str_table.LoadText(L"TXT_OPT_PLAY_DEVICE_NAME_SDL_DEFAULT");
86         d.driver = L"";
87         d.flags = 0;
88         theApp.m_output_devices.clear();
89         theApp.m_output_devices.push_back(d);
90         int device_index = 0;
91         for (auto i = devices.begin(); i != devices.end(); i++) {
92             DeviceInfo d;
93             d.index = device_index++;
94             d.name = *i;
95             d.driver = L"";
96             d.flags = 0;
97             theApp.m_output_devices.push_back(d);
98         }
99         std::string ver("ffmpeg core version: ");
100         ver += ffmpeg_core_version_str();
101         ver += "\n";
102         OutputDebugStringA(ver.c_str());
103         ffmpeg_core_dump_library_version(1, AV_LOG_INFO);
104         ffmpeg_core_dump_ffmpeg_configuration(1, AV_LOG_INFO);
105     }
106 }
107 
UnInitCore()108 void CFfmpegCore::UnInitCore() {
109     if (settings && IsSucceed()) {
110         free_ffmpeg_core_settings(settings);
111         settings = nullptr;
112     }
113     if (handle) {
114         Close();
115     }
116 }
117 
GetAudioType()118 std::wstring CFfmpegCore::GetAudioType() {
119     return L"";
120 }
121 
GetChannels()122 int CFfmpegCore::GetChannels() {
123     if (IsSucceed() && handle) {
124         return ffmpeg_core_get_channels(handle);
125     } else return 0;
126 }
127 
GetFReq()128 int CFfmpegCore::GetFReq() {
129     if (IsSucceed() && handle) {
130         return ffmpeg_core_get_freq(handle);
131     } else return 0;
132 }
133 
GetSoundFontName()134 std::wstring CFfmpegCore::GetSoundFontName() {
135     return L"";
136 }
137 
Open(const wchar_t * file_path)138 void CFfmpegCore::Open(const wchar_t* file_path) {
139     if (!IsSucceed()) return;
140     if (handle) {
141         Close();
142     }
143     if (file_path) recent_file = file_path;
144     const wchar_t* device = nullptr;
145     if (theApp.m_play_setting_data.device_selected < static_cast<int>(theApp.m_output_devices.size()) && theApp.m_play_setting_data.device_selected) {
146         device = theApp.m_output_devices[theApp.m_play_setting_data.device_selected].name.c_str();
147     }
148     if (!settings) settings = ffmpeg_core_init_settings();
149     int re = ffmpeg_core_open3(file_path, &handle, settings, device);
150     if (re) {
151         err = re;
152     }
153 }
154 
Close()155 void CFfmpegCore::Close() {
156     if (IsSucceed() && handle) {
157         free_music_handle(handle);
158         handle = nullptr;
159         err = 0;
160     }
161 }
162 
Play()163 void CFfmpegCore::Play() {
164     if (!IsSucceed()) return;
165     if (!handle && !recent_file.empty()) {
166         Open(recent_file.c_str());
167     }
168     if (handle) {
169         ffmpeg_core_play(handle);
170     }
171 }
172 
Pause()173 void CFfmpegCore::Pause() {
174     if (IsSucceed() && handle) {
175         ffmpeg_core_pause(handle);
176     }
177 }
178 
Stop()179 void CFfmpegCore::Stop() {
180     Close();
181 }
182 
SetVolume(int volume)183 void CFfmpegCore::SetVolume(int volume) {
184     if (!IsSucceed()) return;
185     if (handle) {
186         int re = ffmpeg_core_set_volume(handle, volume);
187         if (re) {
188             err = re;
189         }
190     } else {
191         ffmpeg_core_settings_set_volume(settings, volume);
192     }
193 }
194 
SetSpeed(float speed)195 void CFfmpegCore::SetSpeed(float speed) {
196     if (!IsSucceed()) return;
197     if (handle) {
198         int re = ffmpeg_core_set_speed(handle, speed);
199         if (re) {
200             err = re;
201         }
202     } else {
203         ffmpeg_core_settings_set_speed(settings, speed);
204     }
205 }
206 
SetPitch(int pitch)207 void CFfmpegCore::SetPitch(int pitch)
208 {
209 }
210 
SongIsOver()211 bool CFfmpegCore::SongIsOver() {
212     if (IsSucceed() && handle) {
213         return ffmpeg_core_song_is_over(handle);
214     } else return false;
215 }
216 
GetCurPosition()217 int CFfmpegCore::GetCurPosition() {
218     if (IsSucceed() && handle) {
219         return static_cast<int>(ffmpeg_core_get_cur_position(handle) / 1000);
220     } else return 0;
221 }
222 
GetSongLength()223 int CFfmpegCore::GetSongLength() {
224     if (IsSucceed() && handle) {
225         int64_t length = ffmpeg_core_get_song_length(handle);
226         if (length != INT64_MIN)
227             return static_cast<int>(length / 1000);
228         else
229             return 0;
230     } else return 0;
231 }
232 
SetCurPosition(int position)233 void CFfmpegCore::SetCurPosition(int position) {
234     if (IsSucceed() && handle && GetSongLength() != 0) {    // 时长为0(获取失败)时seek(0)会卡死
235         int re = ffmpeg_core_seek(handle, (int64_t)position * 1000);
236         if (re) {
237             err = re;
238         }
239     }
240 }
241 
GetAudioInfo(SongInfo & song_info,int flag)242 void CFfmpegCore::GetAudioInfo(SongInfo& song_info, int flag) {
243     if (!handle || !IsSucceed()) return;
244     if (flag & AF_LENGTH) song_info.end_pos.fromInt(GetSongLength());
245     if (flag & AF_CHANNEL_INFO) {
246         song_info.freq = ffmpeg_core_get_freq(handle);
247         song_info.bits = ffmpeg_core_get_bits(handle);
248         song_info.channels = ffmpeg_core_get_channels(handle);
249     }
250     if (flag & AF_BITRATE) {
251         song_info.bitrate = static_cast<short>(ffmpeg_core_get_bitrate(handle) / 1000);
252     }
253     if (flag & AF_TAG_INFO) {
254         CAudioTag audio_tag(song_info);
255         audio_tag.GetAudioRating();
256         if (!audio_tag.GetAudioTag())       //如果taglib获取信息失败,则使用ffmpeg获取标签信息
257         {
258             song_info.title = GetTitle();
259             song_info.artist = GetArtist();
260             song_info.album = GetAlbum();
261             song_info.comment = GetComment();
262             song_info.genre = GetGenre();
263             song_info.year = GetYear();
264             song_info.track = GetTrackNum();
265         }
266     }
267 }
268 
GetAudioInfo(const wchar_t * file_path,SongInfo & song_info,int flag)269 void CFfmpegCore::GetAudioInfo(const wchar_t* file_path, SongInfo& song_info, int flag) {
270     if (!IsSucceed()) return;
271     MusicInfoHandle* h = nullptr;
272     int re = ffmpeg_core_info_open(file_path, &h);
273     if (re || !h) return;
274     if (flag & AF_LENGTH) {
275         int64_t length = ffmpeg_core_info_get_song_length(h);
276         if (length != INT64_MIN)
277             song_info.end_pos.fromInt(static_cast<int>(length / 1000));
278         else
279             song_info.end_pos.fromInt(0);
280     }
281     if (flag & AF_CHANNEL_INFO) {
282         song_info.freq = ffmpeg_core_info_get_freq(h);
283         song_info.bits = ffmpeg_core_info_get_bits(h);
284         song_info.channels = ffmpeg_core_info_get_channels(h);
285     }
286     if (flag & AF_BITRATE) {
287         song_info.bitrate = static_cast<short>(ffmpeg_core_info_get_bitrate(h) / 1000);
288     }
289     if (flag & AF_TAG_INFO) {
290         if (song_info.file_path.empty())
291             song_info.file_path = file_path;
292         CAudioTag audio_tag(song_info);
293         audio_tag.GetAudioRating();
294         if (!audio_tag.GetAudioTag())       //如果taglib获取信息失败,则使用ffmpeg获取标签信息
295         {
296             song_info.title = GetTitle(h);
297             song_info.artist = GetArtist(h);
298             song_info.album = GetAlbum(h);
299             song_info.comment = GetComment(h);
300             song_info.genre = GetGenre(h);
301             song_info.year = GetYear(h);
302             song_info.track = GetTrackNum(h);
303         }
304     }
305     free_music_info_handle(h);
306 }
307 
IsMidi()308 bool CFfmpegCore::IsMidi() {
309     return false;
310 }
311 
IsMidiConnotPlay()312 bool CFfmpegCore::IsMidiConnotPlay() {
313     return false;
314 }
315 
GetMidiInfo()316 MidiInfo CFfmpegCore::GetMidiInfo() {
317     return MidiInfo();
318 }
319 
GetMidiInnerLyric()320 std::wstring CFfmpegCore::GetMidiInnerLyric() {
321     return L"";
322 }
323 
MidiNoLyric()324 bool CFfmpegCore::MidiNoLyric() {
325     return true;
326 }
327 
GetPlayingState()328 PlayingState CFfmpegCore::GetPlayingState() {
329     if (IsSucceed() && handle) {
330         return ffmpeg_core_is_playing(handle) ? PlayingState::PS_PLAYING : PlayingState::PS_PAUSED;
331     } else return PlayingState::PS_STOPED;
332 }
333 
ApplyEqualizer(int channel,int gain)334 void CFfmpegCore::ApplyEqualizer(int channel, int gain) {
335     if (!IsSucceed()) return;
336     channel = GetEqChannelFreq(channel);
337     if (handle) {
338         int re = ffmpeg_core_set_equalizer_channel(handle, channel, gain);
339         if (re) {
340             err = re;
341         }
342     } else {
343         ffmpeg_core_settings_set_equalizer_channel(settings, channel, gain);
344     }
345 }
346 
SetReverb(int mix,int time)347 void CFfmpegCore::SetReverb(int mix, int time) {
348 }
349 
ClearReverb()350 void CFfmpegCore::ClearReverb() {
351 }
352 
GetFFTData(float fft_data[FFT_SAMPLE])353 void CFfmpegCore::GetFFTData(float fft_data[FFT_SAMPLE]) {
354     if (handle && IsSucceed()) {
355         memset(fft_data, 0, sizeof(fft_data));
356         ffmpeg_core_get_fft_data(handle, fft_data, FFT_SAMPLE);
357     } else {
358         memset(fft_data, 0, sizeof(fft_data));
359     }
360 }
361 
GetErrorCode()362 int CFfmpegCore::GetErrorCode() {
363     if (err) {
364         int tmp = err;
365         err = 0;
366         return tmp;
367     }
368     // 不返回下层的错误,以免当下层重新打开文件时,即使这里返回0,上层依旧认为有错误
369     // if (handle) return ffmpeg_core_get_error(handle);
370     return 0;
371 }
372 
GetErrorInfo(int error_code)373 std::wstring CFfmpegCore::GetErrorInfo(int error_code) {
374     if (error_code == 0 || !IsSucceed()) return L"";
375     auto tmp = ffmpeg_core_get_err_msg(error_code);
376     if (tmp) {
377         std::wstring re(tmp);
378         ffmpeg_core_free(tmp);
379         return re;
380     }
381     return L"";
382 }
383 
GetErrorInfo()384 std::wstring CFfmpegCore::GetErrorInfo() {
385     return GetErrorInfo(GetErrorCode());
386 }
387 
GetCoreType()388 PlayerCoreType CFfmpegCore::GetCoreType() {
389     return PlayerCoreType::PT_FFMPEG;
390 }
391 
GetFunction()392 bool CFfmpegCore::GetFunction() {
393     bool rtn = true;
394     //获取函数入口
395     free_music_handle = (_free_music_handle)::GetProcAddress(m_dll_module, "free_music_handle");
396     free_music_info_handle = (_free_music_info_handle)::GetProcAddress(m_dll_module, "free_music_info_handle");
397     free_ffmpeg_core_settings = (_free_ffmpeg_core_settings)::GetProcAddress(m_dll_module, "free_ffmpeg_core_settings");
398     free_device_name_list = (_free_device_name_list)::GetProcAddress(m_dll_module, "free_device_name_list");
399     ffmpeg_core_free = (_ffmpeg_core_free)::GetProcAddress(m_dll_module, "ffmpeg_core_free");
400     ffmpeg_core_malloc = (_ffmpeg_core_malloc)::GetProcAddress(m_dll_module, "ffmpeg_core_malloc");
401     ffmpeg_core_realloc = (_ffmpeg_core_realloc)::GetProcAddress(m_dll_module, "ffmpeg_core_realloc");
402     ffmpeg_core_log_format_line = (_ffmpeg_core_log_format_line)::GetProcAddress(m_dll_module, "ffmpeg_core_log_format_line");
403     ffmpeg_core_log_set_callback = (_ffmpeg_core_log_set_callback)::GetProcAddress(m_dll_module, "ffmpeg_core_log_set_callback");
404     ffmpeg_core_log_set_flags = (_ffmpeg_core_log_set_flags)::GetProcAddress(m_dll_module, "ffmpeg_core_log_set_flags");
405     ffmpeg_core_version_str = (_ffmpeg_core_version_str)::GetProcAddress(m_dll_module, "ffmpeg_core_version_str");
406     ffmpeg_core_version = (_ffmpeg_core_version)::GetProcAddress(m_dll_module, "ffmpeg_core_version");
407     ffmpeg_core_dump_library_version = (_ffmpeg_core_dump_library_version)::GetProcAddress(m_dll_module, "ffmpeg_core_dump_library_version");
408     ffmpeg_core_dump_ffmpeg_configuration = (_ffmpeg_core_dump_ffmpeg_configuration)::GetProcAddress(m_dll_module, "ffmpeg_core_dump_ffmpeg_configuration");
409     ffmpeg_core_open = (_ffmpeg_core_open)::GetProcAddress(m_dll_module, "ffmpeg_core_open");
410     ffmpeg_core_open2 = (_ffmpeg_core_open2)::GetProcAddress(m_dll_module, "ffmpeg_core_open2");
411     ffmpeg_core_open3 = (_ffmpeg_core_open3)::GetProcAddress(m_dll_module, "ffmpeg_core_open3");
412     ffmpeg_core_info_open = (_ffmpeg_core_info_open)::GetProcAddress(m_dll_module, "ffmpeg_core_info_open");
413     ffmpeg_core_play = (_ffmpeg_core_play)::GetProcAddress(m_dll_module, "ffmpeg_core_play");
414     ffmpeg_core_pause = (_ffmpeg_core_pause)::GetProcAddress(m_dll_module, "ffmpeg_core_pause");
415     ffmpeg_core_seek = (_ffmpeg_core_seek)::GetProcAddress(m_dll_module, "ffmpeg_core_seek");
416     ffmpeg_core_set_volume = (_ffmpeg_core_set_volume)::GetProcAddress(m_dll_module, "ffmpeg_core_set_volume");
417     ffmpeg_core_set_speed = (_ffmpeg_core_set_speed)::GetProcAddress(m_dll_module, "ffmpeg_core_set_speed");
418     ffmpeg_core_set_equalizer_channel = (_ffmpeg_core_set_equalizer_channel)::GetProcAddress(m_dll_module, "ffmpeg_core_set_equalizer_channel");
419     ffmpeg_core_get_error = (_ffmpeg_core_get_error)::GetProcAddress(m_dll_module, "ffmpeg_core_get_error");
420     ffmpeg_core_get_err_msg = (_ffmpeg_core_get_err_msg)::GetProcAddress(m_dll_module, "ffmpeg_core_get_err_msg");
421     ffmpeg_core_get_err_msg2 = (_ffmpeg_core_get_err_msg2)::GetProcAddress(m_dll_module, "ffmpeg_core_get_err_msg2");
422     ffmpeg_core_get_cur_position = (_ffmpeg_core_get_cur_position)::GetProcAddress(m_dll_module, "ffmpeg_core_get_cur_position");
423     ffmpeg_core_song_is_over = (_ffmpeg_core_song_is_over)::GetProcAddress(m_dll_module, "ffmpeg_core_song_is_over");
424     ffmpeg_core_get_song_length = (_ffmpeg_core_get_song_length)::GetProcAddress(m_dll_module, "ffmpeg_core_get_song_length");
425     ffmpeg_core_info_get_song_length = (_ffmpeg_core_info_get_song_length)::GetProcAddress(m_dll_module, "ffmpeg_core_info_get_song_length");
426     ffmpeg_core_get_channels = (_ffmpeg_core_get_channels)::GetProcAddress(m_dll_module, "ffmpeg_core_get_channels");
427     ffmpeg_core_info_get_channels = (_ffmpeg_core_info_get_channels)::GetProcAddress(m_dll_module, "ffmpeg_core_info_get_channels");
428     ffmpeg_core_get_freq = (_ffmpeg_core_get_freq)::GetProcAddress(m_dll_module, "ffmpeg_core_get_freq");
429     ffmpeg_core_info_get_freq = (_ffmpeg_core_info_get_freq)::GetProcAddress(m_dll_module, "ffmpeg_core_info_get_freq");
430     ffmpeg_core_is_playing = (_ffmpeg_core_is_playing)::GetProcAddress(m_dll_module, "ffmpeg_core_is_playing");
431     ffmpeg_core_get_bits = (_ffmpeg_core_get_bits)::GetProcAddress(m_dll_module, "ffmpeg_core_get_bits");
432     ffmpeg_core_info_get_bits = (_ffmpeg_core_info_get_bits)::GetProcAddress(m_dll_module, "ffmpeg_core_info_get_bits");
433     ffmpeg_core_get_bitrate = (_ffmpeg_core_get_bitrate)::GetProcAddress(m_dll_module, "ffmpeg_core_get_bitrate");
434     ffmpeg_core_info_get_bitrate = (_ffmpeg_core_info_get_bitrate)::GetProcAddress(m_dll_module, "ffmpeg_core_info_get_bitrate");
435     ffmpeg_core_get_metadata = (_ffmpeg_core_get_metadata)::GetProcAddress(m_dll_module, "ffmpeg_core_get_metadata");
436     ffmpeg_core_info_get_metadata = (_ffmpeg_core_info_get_metadata)::GetProcAddress(m_dll_module, "ffmpeg_core_info_get_metadata");
437     ffmpeg_core_get_fft_data = (_ffmpeg_core_get_fft_data)::GetProcAddress(m_dll_module, "ffmpeg_core_get_fft_data");
438     ffmpeg_core_init_settings = (_ffmpeg_core_init_settings)::GetProcAddress(m_dll_module, "ffmpeg_core_init_settings");
439     ffmpeg_core_settings_set_volume = (_ffmpeg_core_settings_set_volume)::GetProcAddress(m_dll_module, "ffmpeg_core_settings_set_volume");
440     ffmpeg_core_settings_set_speed = (_ffmpeg_core_settings_set_speed)::GetProcAddress(m_dll_module, "ffmpeg_core_settings_set_speed");
441     ffmpeg_core_settings_set_cache_length = (_ffmpeg_core_settings_set_cache_length)::GetProcAddress(m_dll_module, "ffmpeg_core_settings_set_cache_length");
442     ffmpeg_core_settings_set_max_retry_count = (_ffmpeg_core_settings_set_max_retry_count)::GetProcAddress(m_dll_module, "ffmpeg_core_settings_set_max_retry_count");
443     ffmpeg_core_settings_set_url_retry_interval = (_ffmpeg_core_settings_set_url_retry_interval)::GetProcAddress(m_dll_module, "ffmpeg_core_settings_set_url_retry_interval");
444     ffmpeg_core_settings_set_equalizer_channel = (_ffmpeg_core_settings_set_equalizer_channel)::GetProcAddress(m_dll_module, "ffmpeg_core_settings_set_equalizer_channel");
445     ffmpeg_core_get_audio_devices = (_ffmpeg_core_get_audio_devices)::GetProcAddress(m_dll_module, "ffmpeg_core_get_audio_devices");
446     //判断是否成功
447     rtn &= (free_device_name_list != NULL);
448     rtn &= (free_music_handle != NULL);
449     rtn &= (free_music_info_handle != NULL);
450     rtn &= (free_ffmpeg_core_settings != NULL);
451     rtn &= (ffmpeg_core_free != NULL);
452     rtn &= (ffmpeg_core_malloc != NULL);
453     rtn &= (ffmpeg_core_realloc != NULL);
454     rtn &= (ffmpeg_core_log_format_line != NULL);
455     rtn &= (ffmpeg_core_log_set_callback != NULL);
456     rtn &= (ffmpeg_core_log_set_flags != NULL);
457     rtn &= (ffmpeg_core_version_str != NULL);
458     rtn &= (ffmpeg_core_version != NULL);
459     rtn &= (ffmpeg_core_dump_library_version != NULL);
460     rtn &= (ffmpeg_core_dump_ffmpeg_configuration != NULL);
461     rtn &= (ffmpeg_core_open != NULL);
462     rtn &= (ffmpeg_core_open2 != NULL);
463     rtn &= (ffmpeg_core_open3 != NULL);
464     rtn &= (ffmpeg_core_info_open != NULL);
465     rtn &= (ffmpeg_core_play != NULL);
466     rtn &= (ffmpeg_core_pause != NULL);
467     rtn &= (ffmpeg_core_seek != NULL);
468     rtn &= (ffmpeg_core_set_volume != NULL);
469     rtn &= (ffmpeg_core_set_speed != NULL);
470     rtn &= (ffmpeg_core_set_equalizer_channel != NULL);
471     rtn &= (ffmpeg_core_get_error != NULL);
472     rtn &= (ffmpeg_core_get_err_msg != NULL);
473     rtn &= (ffmpeg_core_get_err_msg2 != NULL);
474     rtn &= (ffmpeg_core_get_cur_position != NULL);
475     rtn &= (ffmpeg_core_song_is_over != NULL);
476     rtn &= (ffmpeg_core_get_song_length != NULL);
477     rtn &= (ffmpeg_core_info_get_song_length != NULL);
478     rtn &= (ffmpeg_core_get_channels != NULL);
479     rtn &= (ffmpeg_core_info_get_channels != NULL);
480     rtn &= (ffmpeg_core_get_freq != NULL);
481     rtn &= (ffmpeg_core_info_get_freq != NULL);
482     rtn &= (ffmpeg_core_is_playing != NULL);
483     rtn &= (ffmpeg_core_get_bits != NULL);
484     rtn &= (ffmpeg_core_info_get_bits != NULL);
485     rtn &= (ffmpeg_core_get_bitrate != NULL);
486     rtn &= (ffmpeg_core_info_get_bitrate != NULL);
487     rtn &= (ffmpeg_core_get_metadata != NULL);
488     rtn &= (ffmpeg_core_info_get_metadata != NULL);
489     rtn &= (ffmpeg_core_get_fft_data != NULL);
490     rtn &= (ffmpeg_core_init_settings != NULL);
491     rtn &= (ffmpeg_core_settings_set_volume != NULL);
492     rtn &= (ffmpeg_core_settings_set_speed != NULL);
493     rtn &= (ffmpeg_core_settings_set_cache_length != NULL);
494     rtn &= (ffmpeg_core_settings_set_max_retry_count != NULL);
495     rtn &= (ffmpeg_core_settings_set_url_retry_interval != NULL);
496     rtn &= (ffmpeg_core_settings_set_equalizer_channel != NULL);
497     rtn &= (ffmpeg_core_get_audio_devices != NULL);
498     if (ffmpeg_core_version) {
499         version = ffmpeg_core_version();
500         if (version > FFMPEG_CORE_VERSION(1, 0, 0, 0)) {
501             ffmpeg_core_is_wasapi_supported = (_ffmpeg_core_is_wasapi_supported)::GetProcAddress(m_dll_module, "ffmpeg_core_is_wasapi_supported");
502             ffmpeg_core_settings_set_use_WASAPI = (_ffmpeg_core_settings_set_use_WASAPI)::GetProcAddress(m_dll_module, "ffmpeg_core_settings_set_use_WASAPI");
503             ffmpeg_core_settings_set_enable_exclusive = (_ffmpeg_core_settings_set_enable_exclusive)::GetProcAddress(m_dll_module, "ffmpeg_core_settings_set_enable_exclusive");
504             ffmpeg_core_settings_set_max_wait_time = (_ffmpeg_core_settings_set_max_wait_time)::GetProcAddress(m_dll_module, "ffmpeg_core_settings_set_max_wait_time");
505             rtn &= (ffmpeg_core_is_wasapi_supported != NULL);
506             rtn &= (ffmpeg_core_settings_set_use_WASAPI != NULL);
507             rtn &= (ffmpeg_core_settings_set_enable_exclusive != NULL);
508             rtn &= (ffmpeg_core_settings_set_max_wait_time != NULL);
509         }
510     }
511     return rtn;
512 }
513 
GetMetadata(std::string key,MusicInfoHandle * h)514 std::wstring CFfmpegCore::GetMetadata(std::string key, MusicInfoHandle* h) {
515     if (!IsSucceed()) return L"";
516     if (h) {
517         auto r = ffmpeg_core_info_get_metadata(h, key.c_str());
518         if (!r) return L"";
519         std::wstring re(r);
520         ffmpeg_core_free(r);
521         return re;
522     }
523     if (!handle) return L"";
524     auto r = ffmpeg_core_get_metadata(handle, key.c_str());
525     if (!r) return L"";
526     std::wstring re(r);
527     ffmpeg_core_free(r);
528     return re;
529 }
530 
GetTitle(MusicInfoHandle * h)531 std::wstring CFfmpegCore::GetTitle(MusicInfoHandle* h) {
532     return GetMetadata("title", h);
533 }
534 
GetArtist(MusicInfoHandle * h)535 std::wstring CFfmpegCore::GetArtist(MusicInfoHandle* h) {
536     return GetMetadata("artist", h);
537 }
538 
GetAlbum(MusicInfoHandle * h)539 std::wstring CFfmpegCore::GetAlbum(MusicInfoHandle* h) {
540     return GetMetadata("album", h);
541 }
542 
GetComment(MusicInfoHandle * h)543 std::wstring CFfmpegCore::GetComment(MusicInfoHandle* h) {
544     auto re = GetMetadata("comment", h);
545     if (!re.empty()) return re;
546     return GetMetadata("description", h);
547 }
548 
GetGenre(MusicInfoHandle * h)549 std::wstring CFfmpegCore::GetGenre(MusicInfoHandle* h) {
550     return GetMetadata("genre", h);
551 }
552 
GetDate(MusicInfoHandle * h)553 std::wstring CFfmpegCore::GetDate(MusicInfoHandle* h) {
554     return GetMetadata("date", h);
555 }
556 
GetYear(MusicInfoHandle * h)557 unsigned short CFfmpegCore::GetYear(MusicInfoHandle* h) {
558     auto r = GetDate(h);
559     if (r.empty()) return 0;
560     unsigned short year = 0;
561     if (swscanf_s(r.c_str(), L"%hu", &year) == 1) return year;
562     return 0;
563 }
564 
GetTrack(MusicInfoHandle * h)565 std::wstring CFfmpegCore::GetTrack(MusicInfoHandle* h) {
566     return GetMetadata("track", h);
567 }
568 
GetTrackNum(MusicInfoHandle * h)569 int CFfmpegCore::GetTrackNum(MusicInfoHandle* h) {
570     auto r = GetTrack(h);
571     if (r.empty()) return 0;
572     int track;
573     if (swscanf_s(r.c_str(), L"%i", &track) == 1) return track;
574     return 0;
575 }
576 
LogCallback(void * ptr,int level,const char * fmt,va_list vl)577 void CFfmpegCore::LogCallback(void* ptr, int level, const char* fmt, va_list vl) {
578     if (level > AV_LOG_VERBOSE) return;
579     CFfmpegCore* ffmpeg_core = dynamic_cast<CFfmpegCore*>(CPlayer::GetInstance().GetPlayerCore());
580     if (ffmpeg_core == nullptr)
581         return;
582     char buf[1024];
583     int print = 1;
584     int r = ffmpeg_core->ffmpeg_core_log_format_line(ptr, level, fmt, vl, buf, sizeof(buf), &print);
585     if (r > 0) {
586         std::wstring s = CCommon::StrToUnicode(std::string(buf, r), CodeType::UTF8);
587         if (s.find(L"Last message repeated") != -1) {
588             return;
589         }
590         OutputDebugStringW(s.c_str());
591         if (level <= AV_LOG_ERROR) {
592             if (s.back() == '\n') {
593                 s.pop_back();
594             }
595             if (last_ffmpeg_core_error_cache.empty() || last_ffmpeg_core_error_cache != s) {
596                 last_ffmpeg_core_error_cache = s;
597                 theApp.WriteLog(s);
598             }
599         }
600     }
601 }
602 
UpdateSettings()603 void CFfmpegCore::UpdateSettings() {
604     SetCacheLength(theApp.m_play_setting_data.ffmpeg_core_cache_length);
605     SetMaxRetryCount(theApp.m_play_setting_data.ffmpeg_core_max_retry_count);
606     SetUrlRetryInterval(theApp.m_play_setting_data.ffmpeg_core_url_retry_interval);
607     EnableWASAPI(theApp.m_play_setting_data.ffmpeg_core_enable_WASAPI);
608     EnableExclusiveMode(theApp.m_play_setting_data.ffmpeg_core_enable_WASAPI_exclusive_mode);
609     SetMaxWaitTime(theApp.m_play_setting_data.ffmpeg_core_max_wait_time);
610 }
611 
SetCacheLength(int cache_length)612 void CFfmpegCore::SetCacheLength(int cache_length) {
613     if (settings && IsSucceed()) {
614         ffmpeg_core_settings_set_cache_length(settings, cache_length);
615     }
616 }
617 
SetMaxRetryCount(int max_retry_count)618 void CFfmpegCore::SetMaxRetryCount(int max_retry_count) {
619     if (settings && IsSucceed()) {
620         ffmpeg_core_settings_set_max_retry_count(settings, max_retry_count);
621     }
622 }
623 
SetUrlRetryInterval(int url_retry_interval)624 void CFfmpegCore::SetUrlRetryInterval(int url_retry_interval) {
625     if (settings && IsSucceed()) {
626         ffmpeg_core_settings_set_url_retry_interval(settings, url_retry_interval);
627     }
628 }
629 
GetEqChannelFreq(int channel)630 int CFfmpegCore::GetEqChannelFreq(int channel) {
631     switch (channel) {
632         case 0:
633             return 80;
634         case 1:
635             return 125;
636         case 2:
637             return 250;
638         case 3:
639             return 500;
640         case 4:
641             return 1000;
642         case 5:
643             return 1500;
644         case 6:
645             return 2000;
646         case 7:
647             return 4000;
648         case 8:
649             return 8000;
650         case 9:
651             return 16000;
652         default:
653             return 0;
654     }
655 }
656 
GetAudioDevices()657 std::list<std::wstring> CFfmpegCore::GetAudioDevices() {
658     if (!IsSucceed()) return {};
659     auto d = ffmpeg_core_get_audio_devices();
660     if (!d) return {};
661     std::list<std::wstring> l;
662     l.push_back(CCommon::StrToUnicode(d->device, CodeType::UTF8));
663     auto t = d;
664     while (t->next) {
665         t = t->next;
666         l.push_back(CCommon::StrToUnicode(t->device, CodeType::UTF8));
667     }
668     free_device_name_list(&d);
669     return l;
670 }
671 
EncodeAudio(SongInfo song_info,const wstring & dest_file_path,EncodeFormat encode_format,void * encode_para,int dest_freq,EncodeAudioProc proc)672 bool CFfmpegCore::EncodeAudio(SongInfo song_info, const wstring& dest_file_path, EncodeFormat encode_format, void* encode_para, int dest_freq, EncodeAudioProc proc)
673 {
674     return false;
675 }
676 
InitEncoder()677 bool CFfmpegCore::InitEncoder()
678 {
679     return false;
680 }
681 
UnInitEncoder()682 void CFfmpegCore::UnInitEncoder()
683 {
684 }
685 
IsFreqConvertAvailable()686 bool CFfmpegCore::IsFreqConvertAvailable()
687 {
688     return false;
689 }
690 
GetVersion()691 int32_t CFfmpegCore::GetVersion() {
692     return version;
693 }
694 
IsWASAPISupported()695 bool CFfmpegCore::IsWASAPISupported() {
696     if (ffmpeg_core_is_wasapi_supported) {
697         return ffmpeg_core_is_wasapi_supported();
698     }
699     return false;
700 }
701 
EnableWASAPI(bool enable)702 void CFfmpegCore::EnableWASAPI(bool enable) {
703     if (settings && IsSucceed() && ffmpeg_core_settings_set_use_WASAPI) {
704         ffmpeg_core_settings_set_use_WASAPI(settings, enable ? 1 : 0);
705     }
706 }
707 
EnableExclusiveMode(bool enable)708 void CFfmpegCore::EnableExclusiveMode(bool enable) {
709     if (settings && IsSucceed() && ffmpeg_core_settings_set_enable_exclusive) {
710         ffmpeg_core_settings_set_enable_exclusive(settings, enable ? 1 : 0);
711     }
712 }
713 
SetMaxWaitTime(int max_wait_time)714 void CFfmpegCore::SetMaxWaitTime(int max_wait_time) {
715     if (settings && IsSucceed() && ffmpeg_core_settings_set_max_wait_time) {
716         ffmpeg_core_settings_set_max_wait_time(settings, max_wait_time);
717     }
718 }
719