How do I know the format of audio file? - c++

I want to make a music player and I want to filter out files not audio file on opening.
Should I use QAudioDecoder?
But every file I checked with QAudioDecoder tells me the same codec "audio/pcm".
QAudioDecoder decoder;
decoder.setSourceFilename(fileUrl.toLocalFile());
qDebug() << decoder.audioFormat().codec();
How do I know if the audio file's format is supported by Qt media player by not just checking if the file's name ends with ".mp3" or ".wav"?
And I found that some files' duration incorrect when playing on my music player.
But when I play the file with other music player apps, it gives correct duration on other music players.
Or my app can't play some files but others can.
the console says :
DirectShowPlayerService::doSetUrlSource: Unresolved error code
0x80070002 (?t?Χ??????w?????C)
but after I change the file name, it can be opened.
How should I fix those on my music player instead of fixing the files' probably wrong or unsupported formats one by one?
I wrote this code to check if the file I opened is a supported audio file.
QMediaPlayer audioChecker;
audioChecker.setMedia(fileUrl);
qDebug() << audioChecker.media().canonicalUrl().fileName();
qDebug() << audioChecker.isAudioAvailable();
if(audioChecker.error() == QMediaPlayer::NoError) {
qDebug() << "no error";
}
if(audioChecker.error() == QMediaPlayer::FormatError) {
qDebug() << "format error";
}
and it tells me no error no matter what file I tested.
console:
"musicplayer.exe"
false
no error
"musicplayer.exe"
false
no error
"musicplayer.ilk"
false
no error
"musicplayer.exe"
false
no error
"a song.mp3"
false
no error
But how can files not audio file get no error?
Why do audio file's audio not available?
Never mind. I just read that setMedia() return immediately and doesn't wait for the media to be loaded. so it's normal it gets no audio and no error because it's not loaded.
I guess I'll make a thread class to check my file.
By the way, incorrect duration of the file is fixed somehow. Does it relate to LAV Splitter?

From Qt's documentation:
For playing media or audio files that are not simple, uncompressed audio, you can use the QMediaPlayer C++ class […] The compressed audio formats supported does depend on the operating system environment, and also what media plugins the user may have installed.
A simple example of how to use the QMediaPlayer class:
player = new QMediaPlayer;
// ...
player->setMedia(QUrl::fromLocalFile("/Users/me/Music/coolsong.mp3"));
player->setVolume(50);
player->play();
To verify that the codec is supported, you can use the error() method of the QMediaPlayer class which will return you an error code (see the documentation).
So, after calling setMedia(), you can do something like:
if (player->error() == QMediaPlayer::FormatError)
{
// Codec/format unsupported
}
About the error code you get when opening files:
check that you have no \ characters in your path (if you have some, escape them with another \)
check if you have spaces, special characters, etc.

About how to check audio format in file without check its suffix, there's a tool names mediainfo, with the command line tool run as below:
mediainfo -f [filepath]
You'll get the full information about the file, both video and audio if they exists. And among these parameters, there's a "format" value under "Audio" category, that indicates the actual audio format inside. eg. AAC/AC3
About the file can be played after name changed, I consider maybe there are some space characters in the filename, or the Player just can't access the file specified by name.

Related

Allegro5 C++: Audio sample can't be loaded

I'm trying to insert a song that plays on a loop in my c++ Allegro 5 game. It keeps saying that it can't load the audio.
I have:
tried to use .wav and .ogg files, both did not work.
put the audio file in the correct directory.
created a function to detect the error.
initialized al_init_acodec_addon() and al_install_audio()
ALLEGRO_SAMPLE* song = al_load_sample("liar.ogg");
void game_begin()
{
if (!song)
{
printf( "Audio clip sample not loaded!\n" );
show_err_msg(-6);
}
//Loop the song until the display closes
al_play_sample(song, 1,0,1,ALLEGRO_PLAYMODE_LOOP, NULL);
Basically the console almost always prints out the error message no matter what I do.
Is this a known Allegro 5 problem? I still can't think of a way to fix this...
On a side note, I have tested loading & playing audio in another project file and it worked. Is my file cursed? :(
:)
Try to put it in THIS ORDER before loading samples:
if(!al_init())
return -1;
if(!al_install_audio())
return -2;
if!(!al_init_acodec_addon()) // after installing audio
return -3;
if(!al_reserve_samples(1))
return -4;
And what do you mean by correct directory?

How to check whether a given file is a valid video file in C++?

I tried to do it using OpenCV:
std::string input_name = "<path to file>";
cv::VideoCapture cap(input_name);
if(!cap.isOpened()) printf("Invalid video\n");
However, when I try passing a .txt file, VideoCapture reads it successfully for unknown reasons. When I try to find the number of frames in the video,
if(cap.get(cv::CV_CAP_PROP_FRAME_COUNT) == 0) printf("Invalid video\n");
I get a different number of frames each time I execute. I also tried finding the width and height of a frame in the file,
cv::Mat Frame;
if(!cap.read(Frame)) printf("Cannot read frame\n");
else
{
printf("Frame width is %d\n", Frame.cols);
printf("Frame height is %d\n", Frame.rows);
}
their values are 640 and 400 respectively. Why is this happening? Is there a way to check if a given file is a valid video file preferably using OpenCV?
The only really good way to determine if a file is "valid", is to read its content with an appropriate reader-function that understands that very format. There is no simple, universal marker to say "this is a genuine video file, and can't be something else" - and even if there was, someone could on purpose or by mistake put that in the file so that it looks like a "real video", but isn't when you read the rest of the information. Since there are dozens of different video file formats, it's hard to do something more sensible than "try it, see what happens".
As discussed in another answer, cv::VideoCapture::read() will read the file and return an error indication if the file is not valid. If you want to distinguish between "file doesn't exist", you could do some checking before you try to read it, so you can say "file doesn't exist" as opposed to "sorry, but it seems like that's not a valid video file" - although the latter does apply to "there is no such file" too.
Note that I expect cv::VideoCapture to say isOpened() if the file exists, so for a text-file or PDF, it will happily accept that as "opened". You have to actually try to READ the file to tell if it's a video file. However, the documentation for both ::get and ::read is pretty useless in respect of "What happens on bad input", it almost seems like the functions are designed to only work with valid input.
you can use the method VideoCapture::read(), that will return false if:
the video is corrupt
the string path is pointing to an invalid file
example:
cv::VideoCapture cap(input_name);
auto x = cap.read(im);
I'm not familiar with openCV but you can always check for file extension.
kdt wrote a method for this in this question
https://stackoverflow.com/a/874160/4612406
bool hasEnding (std::string const &fullString, std::string const &ending)
{
if (fullString.length() >= ending.length()) {
return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
} else {
return false;
}
}
Just pass the name of the file and the file extension you want like ".mp4". You can change this method to take vector for ending string and check for every string in the vector where you can place .mp4 .avi etc.

Playing mp4 video using Phonon

I'm trying to write a very simple video player using QT and Phonon, on Windows. My backend is phonon_ds94. First of all, here is the code when I click on "Play" :
if (!this->_files.empty()) {
QString file = this->_files.front();
this->_files.pop();
Phonon::MediaSource _src(file);
this->ui.videoPlayer->play(_src);
}
(Here, file is a std::queue of files to read)
If I want to play a .avi ou .wmv, everything works fine. My video play, it's perfect.
But when I want to play a .mp4 file, nothing happen. The videoPlayer stay black.
I've search on the web and see that there is a BackendCapabilities::availableMimeTypes, so I've try it to be sure that my backend is compatible with mp4 - it's in the list. Here is the list of available mime types:
application/vnd.ms-wpl application/x-mplayer2 application/x-ms-wmd
application/x-ms-wmz audio/3gpp audio/3gpp2 audio/aiff audio/basic
audio/mid audio/midi audio/mp3 audio/mp4 audio/mpeg audio/mpegurl
audio/mpg audio/vnd.dlna.adts audio/wav audio/x-aiff audio/x-mid
audio/x-midi audio/x-mp3 audio/x-mpeg audio/x-mpegurl audio/x-mpg
audio/x-ms-wax audio/x-ms-wma audio/x-wav midi/mid unknown video/3gpp
video/3gpp2 video/avi video/mp4 video/mpeg video/mpg video/msvideo
video/quicktime video/vnd.dlna.mpeg-tts video/x-mpeg video/x-mpeg2a
video/x-ms-asf video/x-ms-asf-plugin video/x-ms-wm video/x-ms-wmv
video/x-ms-wmx video/x-ms-wvx video/x-msvideo vnd.ms.wmhtml
I've also connected the stateChanged signal of the mediaObject to a slot, and when I try to read my video, there is an error saying that file format is not supported.
How can I have Phonon to support it? Should I install a codec pack, even if mp4 is in my list?
I recently had a similar problem and after trying a number of codec packs, here is the one that worked.
K Lite Mega Codec Pack
If you go into the advanced install, you can uncheck the "Tools", "Program" (Windows Media Player Classic), "Shell Extension", and later uncheck the free browser toolbars that come with it, you end up with just the codecs.
Afterwards I have been able to play anything on Windows using the qmediaplayer example program included in the Demos folder of the QtSDK.

play .wav with QSound (Qt) no sound exist

I tried to play .wav file in Qt by using QSound::play
I've tried this code:
QSound::play("airplane.wav");
No error when build but when run there is no sound?!
This rang a bell for me, so I found the code I use to handle sounds. Our platform is Windows, so this is what works for us. I wrapped all this up in a player class. My notes to myself said that QSound wants absolute paths, in platform format (found by examining the QSound code). So try getting the file path by something like this
// (note the "sSoundPath" variable is set to where we store our sound files).
static const QString sSoundPath("./resources/sounds/");
elsewhere...
// QSound wants absolute paths, in platform format
QFileInfo fileInfo(soundFile);
if (fileInfo.isRelative())
{
// we assume one of our own sound files in a relative path
fileInfo.setFile(sSoundPath + soundFile);
fileInfo.makeAbsolute();
}
if (!fileInfo.exists())
{
return false;
}
mSoundFile = QDir::toNativeSeparators(fileInfo.filePath());
Now you can go ahead and try to play the sound file.
I have spent countless days on a similar issue. Basically, I found out that QSound does not support wave files with 44100 Hz sample rate. Check out my discovery at QT5 QSound does not play all wave files
A side note, QSound does not support QT resources, in case you are using one. A workaround is to copy the resource into a file, and then play that file with QSound from the hard drive. Hopefully this info helps.

Edit the frame rate of an avi file

Is it possible to change the frame rate of an avi file using the Video for windows library? I tried the following steps but did not succeed.
AviFileInit
AviFileOpen(OF_READWRITE)
pavi1 = AviFileGetStream
avi_info = AviStreamInfo
avi_info.dwrate = 15
EditStreamSetInfo(dwrate) returns -2147467262.
I'm pretty sure the AVIFile* APIs don't support this. (Disclaimer: I was the one who defined those APIs, but it was over 15 years ago...)
You can't just call EditStreamSetInfo on an plain AVIStream, only one returned from CreateEditableStream.
You could use AVISave, then, but that would obviously re-copy the whole file.
So, yes, you would probably want to do this by parsing the AVI file header enough to find the one DWORD you want to change. There are lots of documents on the RIFF and AVI file formats out there, such as http://www.opennet.ru/docs/formats/avi.txt.
I don't know anything about VfW, but you could always try hex-editing the file. The framerate is probably a field somewhere in the header of the AVI file.
Otherwise, you can script some tool like mencoder[1] to copy the stream to a new file under a different framerate.
[1] http://www.mplayerhq.hu/
HRESULT: 0x80004002 (2147500034)
Name: E_NOINTERFACE
Description: The requested COM interface is not available
Severity code: Failed
Facility Code: FACILITY_NULL (0)
Error Code: 0x4002 (16386)
Does it work if you DON'T call EditStreamSetInfo?
Can you post up the code you use to set the stream info?