So I'm having issues with SDL_mixer, and it seems it plays fine on a good amount of mp3s (although "fine". I noticed that at the beginning of some MP3s there's a small segment of sound corruption, and then it starts playing) but on some MP3 files, there's just absolute silence. It doesn't seem to play anything. And Mix_PlayMusic doesn't seem to return an error, nor does anything else, but it just seems to not make a single sound. Occasionally I'll get a random "Access Reading Violation" when trying to play those files, but every other time, it's just silence.
Here is the code that I'm using to play the MP3 file:
#include "SDL.h"
#include "SDL_mixer.h"
#include <iostream>
bool initLibs()
{
//Initialize all SDL subsystems
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
{
return false;
}
int flags = MIX_INIT_MP3 | MIX_INIT_OGG;
if(Mix_Init(flags)!=flags)
{
return false;
}
//Initialize SDL_mixer
if( Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, AUDIO_S16, 2, 4096 ) == -1 )
{
return false;
}
//If everything initialized fine
return true;
}
int main(int argc, char* argv[])
{
if(!initLibs())
{
std::cout << "error loading libraries" << std::endl;
}
Mix_Music* music = Mix_LoadMUS("test.mp3");
if(music == nullptr)
{
std::cout << "error loading music: " << Mix_GetError() << std::endl;
}
else
{
if(Mix_PlayMusic(music, -1) == -1)
{
std::cout << "error playing music: " << Mix_GetError() << std::endl;
}
}
SDL_Delay(30000);
system("PAUSE");
Mix_HaltMusic();
Mix_FreeMusic(music);
system("PAUSE");
return 0;
}
I was examining the differences in the MP3 files, and it seems that the only real difference is that the ones with LAME3.99 encoding are the ones that don't seem to work. Is anybody able to explain this?
EDIT: After more testing, it also seems to happen on other ones
Related
I am creating a background music player and I wanted to use the MPV C Plugin to do so, but my problem arrives when I disable displaying the video (with check_error(mpv_set_option_string(ctx, "vid", "no"));, this does the job of disabling the video, but then I can't use keys (like q (quit) or > (skip)) anymore... How do I allow them to be used in the terminal without the video GUI?
My Code:
#include <iostream>
#include <mpv/client.h>
static inline void check_error(int status)
{
if (status < 0)
{
std::cout << "mpv API error: " << mpv_error_string(status) << std::endl;
exit(1);
}
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
std::cout << "pass a single media file as argument" << std::endl;
return 1;
}
mpv_handle *ctx = mpv_create();
if (!ctx)
{
std::cout << "failed creating context" << std::endl;
return 1;
}
check_error(mpv_set_option_string(ctx, "input-default-bindings", "yes"));
mpv_set_option_string(ctx, "input-vo-keyboard", "yes");
int val = 1;
check_error(mpv_set_option(ctx, "osc", MPV_FORMAT_FLAG, &val));
check_error(mpv_initialize(ctx));
const char *cmd[] = {"loadfile", argv[1], NULL};
check_error(mpv_command(ctx, cmd));
// THIS IS WHAT I USE TO DISABLE THE VIDEO
// check_error(mpv_set_option_string(ctx, "vid", "no"));
// Let it play, and wait until the user quits.
while (1)
{
mpv_event *event = mpv_wait_event(ctx, 10000);
std::cout << "event: " << mpv_event_name(event->event_id) << std::endl;
if (event->event_id == MPV_EVENT_SHUTDOWN)
break;
}
mpv_terminate_destroy(ctx);
return 0;
}
As you can see with mpv_set_option_string(ctx, "input-default-bindings", "yes") I allow it to use keybinding, but how do I make the keybinding works with just the terminal, since it only works when the GUI is visible? If you ran: mpv path/to/video.mp3 --no-video then the key bindings would still work fine, even without the video GUI.
I'm using the modern ffmpeg API which instructs me to use avcodec_send_packet and avcodec_receive_frame. There are literally no examples of usage in github so I couldn't compare with other code.
My code kinda works, but sometimes, for less than a second or two, the video gets decoded like this:
I thought it was a buffer size problem, so I increased from
const size_t bufferSize = 408304;
to
const size_t bufferSize = 10408304;
Just to see but the problem persists.
(the video size is 1920x1080 and this happens even when there's little motion in the screen)
Here's my decoder class which sends the decoded data to OpenGL in the line
this->frameUpdater->updateData(avFrame->data, avFrame->width, avFrame->height);
void FfmpegDecoder::decodeFrame(uint8_t* frameBuffer, int frameLength)
{
if (frameLength <= 0) return;
int frameFinished = 0;
AVPacket* avPacket = av_packet_alloc();
if (!avPacket) std::cout << "av packet error" << std::endl;
avPacket->size = frameLength;
avPacket->data = frameBuffer;
//Disable ffmpeg annoying output
av_log_set_level(AV_LOG_QUIET);
int sendPacketResult = avcodec_send_packet(avCodecContext, avPacket);
if (!sendPacketResult) {
int receiveFrameResult = avcodec_receive_frame(avCodecContext, avFrame);
if (!receiveFrameResult) {
this->frameUpdater->updateData(avFrame->data, avFrame->width, avFrame->height);
} else if ((receiveFrameResult < 0) && (receiveFrameResult != AVERROR(EAGAIN)) && (receiveFrameResult != AVERROR_EOF)) {
std::cout << "avcodec_receive_frame returned error " << receiveFrameResult /*<< *av_err2str(result).c_str()*/ << std::endl;
} else {
switch (receiveFrameResult) {
//Not exactly an error, we just have to wait for more data
case AVERROR(EAGAIN):
break;
//To be done: what does this error mean? I think it's literally the end of an mp4 file
case AVERROR_EOF:
std::cout << "avcodec_receive_frame AVERROR_EOF" << std::endl;
break;
//To be done: describe what error is this in std cout before stopping
default:
std::cout << "avcodec_receive_frame returned error, stopping..." << receiveFrameResult /*<< av_err2str(result).c_str()*/ << std::endl;
break;
//Error happened, should break anyway
break;
}
}
} else {
switch (sendPacketResult) {
case AVERROR(EAGAIN):
std::cout << "avcodec_send_packet EAGAIN" << std::endl;
break;
case AVERROR_EOF:
std::cout << "avcodec_send_packet AVERROR_EOF" << std::endl;
break;
default:
break;
}
}
}
I think that people who knows how decoding works might know instantly why the image gets decoded like this. It'd be very helpful to know why. Thanks!
I have the following sound loading function:
bool Sound::load(const char* fileName)
{
sound = Mix_LoadWAV(fileName);
if (sound == nullptr)
{
std::cout << "Failed to load sound at path: " << fileName << "SDL_mixer error: " << Mix_GetError();
return false;
}
return true;
}
In Dev-C++, this works, fine. I wanted to use another IDE, so I started using Visual Studio 2017, and configured SDL2 for it. However, when I run this code, from the moment Mix_LoadWAV is called, Visual studio gives the following:
https://imgur.com/a/STnXx
I have searched alot on the internet, but I could not find anything useful that worked for me.
EDIT: as per request, I created a minimal example that still produces the same error.
#include "SDL2\SDL_mixer.h"
#include "SDL2\SDL.h"
#include <iostream>
#undef main
class SoundTest
{
private:
Mix_Chunk* sound = nullptr;
public:
bool load(const char* fileName)
{
sound = Mix_LoadWAV(fileName);
if (sound == nullptr)
{
std::cout << "Failed to load sound at path: " << fileName << "SDL_mixer error: " << Mix_GetError();
return false;
}
return true;
}
};
SDL_Window *window = nullptr;
int main(int argc, char** argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
window = SDL_CreateWindow("Sound bug? ", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 300, 300, SDL_WINDOW_SHOWN);
Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 2, 2048);
SoundTest sound;
sound.load("audio/soundEffect.wav");
while (true)
{
//Do fun stuff with the sound
}
return 0;
}
I want to change VideoStream setting in my program, but it doesn't work
#include <OpenNI.h>
int main()
{
OpenNI::initialize();
Device device;
device.open(ANY_DEVICE);
VideoStream depthStream;
depthStream.create(device, SENSOR_DEPTH);
depthStream.start();
VideoMode depthMode;
depthMode.setFps(20);
depthMode.setResolution(640, 480);
depthMode.setPixelFormat(PIXEL_FORMAT_DEPTH_100_UM);
depthStream.setVideoMode(depthMode);
...
}
Even I change depthStream.start() line after setVideoMode() function, but still doesn't work.
I changed Fps to 24, 20, 5, 1 but it doesn't change anything.
p.s. : This is my simple code, without error handling.
Edit:
Answer:
with the help of dear "api55" i found that my device (Kinect Xbox) support only one mode of videoMode. so I can't change it.
My only supported video is :
FPS:30
Width:640
Height:480
I change the VideoMode succesfully in a code a did before. After creating the VideoStream you should do something like:
rc = depth.create(device, openni::SENSOR_DEPTH);
if (rc != openni::STATUS_OK)
error_manager(3);
// set the new resolution and fps
openni::VideoMode depth_videoMode = depth.getVideoMode();
depth_videoMode.setResolution(frame_width,frame_height);
depth_videoMode.setFps(30);
depth.setVideoMode(depth_videoMode);
rc = depth.start();
if (rc != openni::STATUS_OK)
error_manager(4);
First I get the VideoMode that is inside the stream to conserve the other values and only change what I wanted. I think your code should work, but not all settings work in all cameras. To check the possible settings you can use the function openni::VideoStream::getSensorInfo. The code to check this should be something like:
#include <OpenNI.h>
int main()
{
OpenNI::initialize();
Device device;
device.open(ANY_DEVICE);
VideoStream depthStream;
depthStream.create(device, SENSOR_DEPTH);
depthStream.start();
SensorInfo& info = depthStream.getSensorInfo();
Array& videoModes = info.getSupportedVideoModes();
for (int i = 0; i < videoModes.getSize(); i++){
std::cout << "VideoMode " << i << std::endl;
std::cout << "FPS:" << videoModes[i].getFps() << std::endl;
std::cout << "Width:" << videoModes[i].getResolutionX() << std::endl;
std::cout << "Height:" << videoModes[i].getResolutionY() << std::endl;
}
...
}
I haven't test this last piece of code, so it may have errors, but you get the idea of it. The supported settings change with each camera, but I think the supported FPS in my camera were 15 and 30.
I hope this helps you
I read and tried all the other posts to that topic, but nothing helped. When I try to play music with Mix_PlayChannel() I don't get an error nor do I hear some sound! I tried for hours now and nothing helps. The program just finishes happily. But no sound! I am using Ubuntu 12.04 64bit.
Thanks!
[EDIT]
Here is the code I use:
#include <iostream>
#include <SDL/SDL.h>
#include <SDL/SDL_mixer.h>
int main(int argc, char** argv) {
Mix_Music *music = NULL;
Mix_Chunk *wave = NULL;
SDL_Init(SDL_INIT_AUDIO);
int audio_rate = 44100;
Uint16 audio_format = AUDIO_S16; /* 16-bit stereo */
int audio_channels = 1;
int audio_buffers = 4096;
if(Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers) < 0) {
printf("Unable to open audio!\n");
exit(1);
}
if(Mix_Init(MIX_INIT_MOD) != MIX_INIT_MOD)
std::cout << "errer";
Mix_Volume(-1, MIX_MAX_VOLUME);
music = Mix_LoadMUS("1.wav");
wave = Mix_LoadWAV("1.wav");
if (music == NULL) {
std::cout << "Could not load 1.wav\n";
std::cout << Mix_GetError();
}
if (wave == NULL) {
std::cout << "Could not load 1.wav\n";
std::cout << Mix_GetError();
}
Mix_VolumeChunk(wave, MIX_MAX_VOLUME);
Mix_VolumeMusic(MIX_MAX_VOLUME);
Mix_PlayMusic(music, 0);
std::cout << Mix_GetError();
Mix_FadeInChannelTimed(-1, wave, 0, 100,1);
std::cout << Mix_GetError();
return 1;
}
I try both PlayMusic() and Mix_FadeInChannelTimed(). Both files are loaded correctly but not played. Sound is not muted, wav-file is playable with aplay or other tools. I check with alsamixer that all channels are open and not too low.
I now found out that the program needs to run until the sound has finished playing! I added a usleep() command after the play command and it plays nicely. So that was really mentioned nowhere that PlayMusic() does not keep running.