audio do not stop recording after pause ffmpeg c++ - c++

I am developing an application that record the screen and the audio from microphone. I implemented the pause function stopping video and audio thread on a condition variable, resuming them with a notify on the same condition variable. This is done in captureAudio(), in the main while. In this way works on macOS and linux, where I use avfoudation and alsa respectively, but on windows, with dshow, keep recording audio during the pause, when the thread is waiting on the condition variable. Does anybody know how can I fix this behaviour?
#include "ScreenRecorder.h"
using namespace std;
ScreenRecorder::ScreenRecorder() : pauseCapture(false), stopCapture(false), started(false), activeMenu(true) {
avcodec_register_all();
avdevice_register_all();
width = 1920;
height = 1200;
}
ScreenRecorder::~ScreenRecorder() {
if (started) {
value = av_write_trailer(outAVFormatContext);
if (value < 0) {
cerr << "Error in writing av trailer" << endl;
exit(-1);
}
avformat_close_input(&inAudioFormatContext);
if(inAudioFormatContext == nullptr){
cout << "inAudioFormatContext close successfully" << endl;
}
else{
cerr << "Error: unable to close the inAudioFormatContext" << endl;
exit(-1);
//throw "Error: unable to close the file";
}
avformat_free_context(inAudioFormatContext);
if(inAudioFormatContext == nullptr){
cout << "AudioFormat freed successfully" << endl;
}
else{
cerr << "Error: unable to free AudioFormatContext" << endl;
exit(-1);
}
avformat_close_input(&pAVFormatContext);
if (pAVFormatContext == nullptr) {
cout << "File close successfully" << endl;
}
else {
cerr << "Error: unable to close the file" << endl;
exit(-1);
//throw "Error: unable to close the file";
}
avformat_free_context(pAVFormatContext);
if (pAVFormatContext == nullptr) {
cout << "VideoFormat freed successfully" << endl;
}
else {
cerr << "Error: unable to free VideoFormatContext" << endl;
exit(-1);
}
}
}
/*==================================== VIDEO ==============================*/
int ScreenRecorder::openVideoDevice() throw() {
value = 0;
options = nullptr;
pAVFormatContext = nullptr;
pAVFormatContext = avformat_alloc_context();
string dimension = to_string(width) + "x" + to_string(height);
av_dict_set(&options, "video_size", dimension.c_str(), 0); //option to set the dimension of the screen section to record
#ifdef _WIN32
pAVInputFormat = av_find_input_format("gdigrab");
if (avformat_open_input(&pAVFormatContext, "desktop", pAVInputFormat, &options) != 0) {
cerr << "Couldn't open input stream" << endl;
exit(-1);
}
#elif defined linux
int offset_x = 0, offset_y = 0;
string url = ":0.0+" + to_string(offset_x) + "," + to_string(offset_y); //custom string to set the start point of the screen section
pAVInputFormat = av_find_input_format("x11grab");
value = avformat_open_input(&pAVFormatContext, url.c_str(), pAVInputFormat, &options);
if (value != 0) {
cerr << "Error in opening input device (video)" << endl;
exit(-1);
}
#else
value = av_dict_set(&options, "pixel_format", "0rgb", 0);
if (value < 0) {
cerr << "Error in setting pixel format" << endl;
exit(-1);
}
value = av_dict_set(&options, "video_device_index", "1", 0);
if (value < 0) {
cerr << "Error in setting video device index" << endl;
exit(-1);
}
pAVInputFormat = av_find_input_format("avfoundation");
if (avformat_open_input(&pAVFormatContext, "Capture screen 0:none", pAVInputFormat, &options) != 0) { //TODO trovare un modo per selezionare sempre lo schermo (forse "Capture screen 0")
cerr << "Error in opening input device" << endl;
exit(-1);
}
#endif
//set frame per second
value = av_dict_set(&options, "framerate", "30", 0);
if (value < 0) {
cerr << "Error in setting dictionary value (setting framerate)" << endl;
exit(-1);
}
value = av_dict_set(&options, "preset", "medium", 0);
if (value < 0) {
cerr << "Error in setting dictionary value (setting preset value)" << endl;
exit(-1);
}
/*
value = av_dict_set(&options, "vsync", "1", 0);
if(value < 0){
cerr << "Error in setting dictionary value (setting vsync value)" << endl;
exit(-1);
}
*/
value = av_dict_set(&options, "probesize", "60M", 0);
if (value < 0) {
cerr << "Error in setting probesize value" << endl;
exit(-1);
}
//get video stream infos from context
value = avformat_find_stream_info(pAVFormatContext, nullptr);
if (value < 0) {
cerr << "Error in retrieving the stream info" << endl;
exit(-1);
}
VideoStreamIndx = -1;
for (int i = 0; i < pAVFormatContext->nb_streams; i++) {
if (pAVFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
VideoStreamIndx = i;
break;
}
}
if (VideoStreamIndx == -1) {
cerr << "Error: unable to find video stream index" << endl;
exit(-2);
}
pAVCodecContext = pAVFormatContext->streams[VideoStreamIndx]->codec;
pAVCodec = avcodec_find_decoder(pAVCodecContext->codec_id/*params->codec_id*/);
if (pAVCodec == nullptr) {
cerr << "Error: unable to find decoder video" << endl;
exit(-1);
}
cout << "Insert height and width [h w]: "; //custom screen dimension to record
cin >> h >> w;*/
return 0;
}
/*========================================== AUDIO ============================*/
int ScreenRecorder::openAudioDevice() {
audioOptions = nullptr;
inAudioFormatContext = nullptr;
inAudioFormatContext = avformat_alloc_context();
value = av_dict_set(&audioOptions, "sample_rate", "44100", 0);
if (value < 0) {
cerr << "Error: cannot set audio sample rate" << endl;
exit(-1);
}
value = av_dict_set(&audioOptions, "async", "1", 0);
if (value < 0) {
cerr << "Error: cannot set audio sample rate" << endl;
exit(-1);
}
#if defined linux
audioInputFormat = av_find_input_format("alsa");
value = avformat_open_input(&inAudioFormatContext, "hw:0", audioInputFormat, &audioOptions);
if (value != 0) {
cerr << "Error in opening input device (audio)" << endl;
exit(-1);
}
#endif
#if defined _WIN32
audioInputFormat = av_find_input_format("dshow");
value = avformat_open_input(&inAudioFormatContext, "audio=Microfono (Realtek(R) Audio)", audioInputFormat, &audioOptions);
if (value != 0) {
cerr << "Error in opening input device (audio)" << endl;
exit(-1);
}
#endif
value = avformat_find_stream_info(inAudioFormatContext, nullptr);
if (value != 0) {
cerr << "Error: cannot find the audio stream information" << endl;
exit(-1);
}
audioStreamIndx = -1;
for (int i = 0; i < inAudioFormatContext->nb_streams; i++) {
if (inAudioFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
audioStreamIndx = i;
break;
}
}
if (audioStreamIndx == -1) {
cerr << "Error: unable to find audio stream index" << endl;
exit(-2);
}
}
int ScreenRecorder::initOutputFile() {
value = 0;
outAVFormatContext = nullptr;
outputAVFormat = av_guess_format(nullptr, "output.mp4", nullptr);
if (outputAVFormat == nullptr) {
cerr << "Error in guessing the video format, try with correct format" << endl;
exit(-5);
}
avformat_alloc_output_context2(&outAVFormatContext, outputAVFormat, outputAVFormat->name, "..\\media\\output.mp4");
if (outAVFormatContext == nullptr) {
cerr << "Error in allocating outAVFormatContext" << endl;
exit(-4);
}
/*===========================================================================*/
this->generateVideoStream();
this->generateAudioStream();
//create an empty video file
if (!(outAVFormatContext->flags & AVFMT_NOFILE)) {
if (avio_open2(&outAVFormatContext->pb, "..\\media\\output.mp4", AVIO_FLAG_WRITE, nullptr, nullptr) < 0) {
cerr << "Error in creating the video file" << endl;
exit(-10);
}
}
if (outAVFormatContext->nb_streams == 0) {
cerr << "Output file does not contain any stream" << endl;
exit(-11);
}
value = avformat_write_header(outAVFormatContext, &options);
if (value < 0) {
cerr << "Error in writing the header context" << endl;
exit(-12);
}
return 0;
}
/*=================================== VIDEO ==================================*/
void ScreenRecorder::generateVideoStream() {
//Generate video stream
videoSt = avformat_new_stream(outAVFormatContext, nullptr);
if (videoSt == nullptr) {
cerr << "Error in creating AVFormatStream" << endl;
exit(-6);
}
outVideoCodec = avcodec_find_encoder(AV_CODEC_ID_MPEG4); //AV_CODEC_ID_MPEG4
if (outVideoCodec == nullptr) {
cerr << "Error in finding the AVCodec, try again with the correct codec" << endl;
exit(-8);
}
avcodec_alloc_context3(outAVCodec)
outVideoCodecContext = avcodec_alloc_context3(outVideoCodec);
if (outVideoCodecContext == nullptr) {
cerr << "Error in allocating the codec context" << endl;
exit(-7);
}
//set properties of the video file (stream)
outVideoCodecContext = videoSt->codec;
outVideoCodecContext->codec_id = AV_CODEC_ID_MPEG4;
outVideoCodecContext->codec_type = AVMEDIA_TYPE_VIDEO;
outVideoCodecContext->pix_fmt = AV_PIX_FMT_YUV420P;
outVideoCodecContext->bit_rate = 10000000;
outVideoCodecContext->width = width;
outVideoCodecContext->height = height;
outVideoCodecContext->gop_size = 10;
outVideoCodecContext->global_quality = 500;
outVideoCodecContext->max_b_frames = 2;
outVideoCodecContext->time_base.num = 1;
outVideoCodecContext->time_base.den = 30;
outVideoCodecContext->bit_rate_tolerance = 400000;
if (outVideoCodecContext->codec_id == AV_CODEC_ID_H264) {
av_opt_set(outVideoCodecContext->priv_data, "preset", "slow", 0);
}
if (outAVFormatContext->oformat->flags & AVFMT_GLOBALHEADER) {
outVideoCodecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
value = avcodec_open2(outVideoCodecContext, outVideoCodec, nullptr);
if (value < 0) {
cerr << "Error in opening the AVCodec" << endl;
exit(-9);
}
outVideoStreamIndex = -1;
for (int i = 0; i < outAVFormatContext->nb_streams; i++) {
if (outAVFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_UNKNOWN) {
outVideoStreamIndex = i;
}
}
if (outVideoStreamIndex < 0) {
cerr << "Error: cannot find a free stream index for video output" << endl;
exit(-1);
}
avcodec_parameters_from_context(outAVFormatContext->streams[outVideoStreamIndex]->codecpar, outVideoCodecContext);
}
/*=============================== AUDIO ==================================*/
void ScreenRecorder::generateAudioStream() {
AVCodecParameters* params = inAudioFormatContext->streams[audioStreamIndx]->codecpar;
inAudioCodec = avcodec_find_decoder(params->codec_id);
if (inAudioCodec == nullptr) {
cerr << "Error: cannot find the audio decoder" << endl;
exit(-1);
}
inAudioCodecContext = avcodec_alloc_context3(inAudioCodec);
if (avcodec_parameters_to_context(inAudioCodecContext, params) < 0) {
cout << "Cannot create codec context for audio input" << endl;
}
value = avcodec_open2(inAudioCodecContext, inAudioCodec, nullptr);
if (value < 0) {
cerr << "Error: cannot open the input audio codec" << endl;
exit(-1);
}
//Generate audio stream
outAudioCodecContext = nullptr;
outAudioCodec = nullptr;
int i;
AVStream* audio_st = avformat_new_stream(outAVFormatContext, nullptr);
if (audio_st == nullptr) {
cerr << "Error: cannot create audio stream" << endl;
exit(1);
}
outAudioCodec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if (outAudioCodec == nullptr) {
cerr << "Error: cannot find requested encoder" << endl;
exit(1);
}
outAudioCodecContext = avcodec_alloc_context3(outAudioCodec);
if (outAudioCodecContext == nullptr) {
cerr << "Error: cannot create related VideoCodecContext" << endl;
exit(1);
}
if ((outAudioCodec)->supported_samplerates) {
outAudioCodecContext->sample_rate = (outAudioCodec)->supported_samplerates[0];
for (i = 0; (outAudioCodec)->supported_samplerates[i]; i++) {
if ((outAudioCodec)->supported_samplerates[i] == inAudioCodecContext->sample_rate)
outAudioCodecContext->sample_rate = inAudioCodecContext->sample_rate;
}
}
outAudioCodecContext->codec_id = AV_CODEC_ID_AAC;
outAudioCodecContext->sample_fmt = (outAudioCodec)->sample_fmts ? (outAudioCodec)->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;
outAudioCodecContext->channels = inAudioCodecContext->channels;
outAudioCodecContext->channel_layout = av_get_default_channel_layout(outAudioCodecContext->channels);
outAudioCodecContext->bit_rate = 96000;
outAudioCodecContext->time_base = { 1, inAudioCodecContext->sample_rate };
outAudioCodecContext->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
if ((outAVFormatContext)->oformat->flags & AVFMT_GLOBALHEADER) {
outAudioCodecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
if (avcodec_open2(outAudioCodecContext, outAudioCodec, nullptr) < 0) {
cerr << "error in opening the avcodec" << endl;
exit(1);
}
//find a free stream index
outAudioStreamIndex = -1;
for (i = 0; i < outAVFormatContext->nb_streams; i++) {
if (outAVFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_UNKNOWN) {
outAudioStreamIndex = i;
}
}
if (outAudioStreamIndex < 0) {
cerr << "Error: cannot find a free stream for audio on the output" << endl;
exit(1);
}
avcodec_parameters_from_context(outAVFormatContext->streams[outAudioStreamIndex]->codecpar, outAudioCodecContext);
}
int ScreenRecorder::init_fifo()
{
/* Create the FIFO buffer based on the specified output sample format. */
if (!(fifo = av_audio_fifo_alloc(outAudioCodecContext->sample_fmt,
outAudioCodecContext->channels, 1))) {
fprintf(stderr, "Could not allocate FIFO\n");
return AVERROR(ENOMEM);
}
return 0;
}
int ScreenRecorder::add_samples_to_fifo(uint8_t** converted_input_samples, const int frame_size) {
int error;
/* Make the FIFO as large as it needs to be to hold both,
* the old and the new samples. */
if ((error = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame_size)) < 0) {
fprintf(stderr, "Could not reallocate FIFO\n");
return error;
}
/* Store the new samples in the FIFO buffer. */
if (av_audio_fifo_write(fifo, (void**)converted_input_samples, frame_size) < frame_size) {
fprintf(stderr, "Could not write data to FIFO\n");
return AVERROR_EXIT;
}
return 0;
}
int ScreenRecorder::initConvertedSamples(uint8_t*** converted_input_samples,
AVCodecContext* output_codec_context,
int frame_size) {
int error;
/* Allocate as many pointers as there are audio channels.
* Each pointer will later point to the audio samples of the corresponding
* channels (although it may be NULL for interleaved formats).
*/
if (!(*converted_input_samples = (uint8_t**)calloc(output_codec_context->channels,
sizeof(**converted_input_samples)))) {
fprintf(stderr, "Could not allocate converted input sample pointers\n");
return AVERROR(ENOMEM);
}
/* Allocate memory for the samples of all channels in one consecutive
* block for convenience. */
if (av_samples_alloc(*converted_input_samples, nullptr,
output_codec_context->channels,
frame_size,
output_codec_context->sample_fmt, 0) < 0) {
exit(1);
}
return 0;
}
static int64_t pts = 0;
void ScreenRecorder::captureAudio() {
int ret;
AVPacket* inPacket, * outPacket;
AVFrame* rawFrame, * scaledFrame;
uint8_t** resampledData;
init_fifo();
//allocate space for a packet
inPacket = (AVPacket*)av_malloc(sizeof(AVPacket));
if (!inPacket) {
cerr << "Cannot allocate an AVPacket for encoded video" << endl;
exit(1);
}
av_init_packet(inPacket);
//allocate space for a packet
rawFrame = av_frame_alloc();
if (!rawFrame) {
cerr << "Cannot allocate an AVPacket for encoded video" << endl;
exit(1);
}
scaledFrame = av_frame_alloc();
if (!scaledFrame) {
cerr << "Cannot allocate an AVPacket for encoded video" << endl;
exit(1);
}
outPacket = (AVPacket*)av_malloc(sizeof(AVPacket));
if (!outPacket) {
cerr << "Cannot allocate an AVPacket for encoded video" << endl;
exit(1);
}
//init the resampler
SwrContext* resampleContext = nullptr;
resampleContext = swr_alloc_set_opts(resampleContext,
av_get_default_channel_layout(outAudioCodecContext->channels),
outAudioCodecContext->sample_fmt,
outAudioCodecContext->sample_rate,
av_get_default_channel_layout(inAudioCodecContext->channels),
inAudioCodecContext->sample_fmt,
inAudioCodecContext->sample_rate,
0,
nullptr);
if (!resampleContext) {
cerr << "Cannot allocate the resample context" << endl;
exit(1);
}
if ((swr_init(resampleContext)) < 0) {
fprintf(stderr, "Could not open resample context\n");
swr_free(&resampleContext);
exit(1);
}
while (true) {
if (pauseCapture) {
cout << "Pause audio" << endl;
}
cv.wait(ul, [this]() { return !pauseCapture; });
if (stopCapture) {
break;
}
ul.unlock();
if (av_read_frame(inAudioFormatContext, inPacket) >= 0 && inPacket->stream_index == audioStreamIndx) {
//decode audio routing
av_packet_rescale_ts(outPacket, inAudioFormatContext->streams[audioStreamIndx]->time_base, inAudioCodecContext->time_base);
if ((ret = avcodec_send_packet(inAudioCodecContext, inPacket)) < 0) {
cout << "Cannot decode current audio packet " << ret << endl;
continue;
}
while (ret >= 0) {
ret = avcodec_receive_frame(inAudioCodecContext, rawFrame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if (ret < 0) {
cerr << "Error during decoding" << endl;
exit(1);
}
if (outAVFormatContext->streams[outAudioStreamIndex]->start_time <= 0) {
outAVFormatContext->streams[outAudioStreamIndex]->start_time = rawFrame->pts;
}
initConvertedSamples(&resampledData, outAudioCodecContext, rawFrame->nb_samples);
swr_convert(resampleContext,
resampledData, rawFrame->nb_samples,
(const uint8_t**)rawFrame->extended_data, rawFrame->nb_samp
add_samples_to_fifo(resampledData, rawFrame->nb_samples);
//raw frame ready
av_init_packet(outPacket);
outPacket->data = nullptr;
outPacket->size = 0;
const int frame_size = FFMAX(av_audio_fifo_size(fifo), outAudioCodecContext->frame_size);
scaledFrame = av_frame_alloc();
if (!scaledFrame) {
cerr << "Cannot allocate an AVPacket for encoded video" << endl;
exit(1);
}
scaledFrame->nb_samples = outAudioCodecContext->frame_size;
scaledFrame->channel_layout = outAudioCodecContext->channel_layout;
scaledFrame->format = outAudioCodecContext->sample_fmt;
scaledFrame->sample_rate = outAudioCodecContext->sample_rate;
av_frame_get_buffer(scaledFrame, 0);
while (av_audio_fifo_size(fifo) >= outAudioCodecContext->frame_size) {
ret = av_audio_fifo_read(fifo, (void**)(scaledFrame->data), outAudioCodecContext->frame_size);
scaledFrame->pts = pts;
pts += scaledFrame->nb_samples;
if (avcodec_send_frame(outAudioCodecContext, scaledFrame) < 0) {
cout << "Cannot encode current audio packet " << endl;
exit(1);
}
while (ret >= 0) {
ret = avcodec_receive_packet(outAudioCodecContext, outPacket);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if (ret < 0) {
cerr << "Error during encoding" << endl;
exit(1);
}
av_packet_rescale_ts(outPacket, outAudioCodecContext->time_base, outAVFormatContext->streams[outAudioStreamIndex]->time_base);
outPacket->stream_index = outAudioStreamIndex;
write_lock.lock();
if (av_write_frame(outAVFormatContext, outPacket) != 0)
{
cerr << "Error in writing audio frame" << endl;
}
write_lock.unlock();
av_packet_unref(outPacket);
}
ret = 0;
}
av_frame_free(&scaledFrame);
av_packet_unref(outPacket);
}
}
}
}
int ScreenRecorder::captureVideoFrames() {
int64_t pts = 0;
int flag;
int frameFinished = 0;
bool endPause = false;
int numPause = 0;
ofstream outFile{ "..\\media\\log.txt", ios::out };
int frameIndex = 0;
value = 0;
pAVPacket = (AVPacket*)av_malloc(sizeof(AVPacket));
if (pAVPacket == nullptr) {
cerr << "Error in allocating AVPacket" << endl;
exit(-1);
}
pAVFrame = av_frame_alloc();
if (pAVFrame == nullptr) {
cerr << "Error: unable to alloc the AVFrame resources" << endl;
exit(-1);
}
outFrame = av_frame_alloc();
if (outFrame == nullptr) {
cerr << "Error: unable to alloc the AVFrame resources for out frame" << endl;
exit(-1);
}
int videoOutBuffSize;
int nBytes = av_image_get_buffer_size(outVideoCodecContext->pix_fmt, outVideoCodecContext->width, outVideoCodecContext->height, 32);
uint8_t* videoOutBuff = (uint8_t*)av_malloc(nBytes);
if (videoOutBuff == nullptr) {
cerr << "Error: unable to allocate memory" << endl;
exit(-1);
}
value = av_image_fill_arrays(outFrame->data, outFrame->linesize, videoOutBuff, AV_PIX_FMT_YUV420P, outVideoCodecContext->width, outVideoCodecContext->height, 1);
if (value < 0) {
cerr << "Error in filling image array" << endl;
}
SwsContext* swsCtx_;
if (avcodec_open2(pAVCodecContext, pAVCodec, nullptr) < 0) {
cerr << "Could not open codec" << endl;
exit(-1);
}
swsCtx_ = sws_getContext(pAVCodecContext->width, pAVCodecContext->height, pAVCodecContext->pix_fmt, outVideoCodecContext->width, outVideoCodecContext->height, outVideoCodecContext->pix_fmt, SWS_BICUBIC,
nullptr, nullptr, nullptr);
AVPacket outPacket;
int gotPicture;
time_t startTime;
time(&startTime);
while (true) {
if (pauseCapture) {
cout << "Pause" << endl;
outFile << "/////////////////// Pause ///////////////////" << endl;
cout << "outVideoCodecContext->time_base: " << outVideoCodecContext->time_base.num << ", " << outVideoCodecContext->time_base.den << endl;
}
cv.wait(ul, [this]() { return !pauseCapture; }); //pause capture (not busy waiting)
if (endPause) {
endPause = false;
}
if (stopCapture) //check if the capture has to stop
break;
ul.unlock();
if (av_read_frame(pAVFormatContext, pAVPacket) >= 0 && pAVPacket->stream_index == VideoStreamIndx) {
av_packet_rescale_ts(pAVPacket, pAVFormatContext->streams[VideoStreamIndx]->time_base, pAVCodecContext->time_base);
value = avcodec_decode_video2(pAVCodecContext, pAVFrame, &frameFinished, pAVPacket);
if (value < 0) {
cout << "Unable to decode video" << endl;
}
if (frameFinished) { //frame successfully decoded
//sws_scale(swsCtx_, pAVFrame->data, pAVFrame->linesize, 0, pAVCodecContext->height, outFrame->data, outFrame->linesize);
av_init_packet(&outPacket);
outPacket.data = nullptr;
outPacket.size = 0;
if (outAVFormatContext->streams[outVideoStreamIndex]->start_time <= 0) {
outAVFormatContext->streams[outVideoStreamIndex]->start_time = pAVFrame->pts;
}
//disable warning on the console
outFrame->width = outVideoCodecContext->width;
outFrame->height = outVideoCodecContext->height;
outFrame->format = outVideoCodecContext->pix_fmt;
sws_scale(swsCtx_, pAVFrame->data, pAVFrame->linesize, 0, pAVCodecContext->height, outFrame->data, outFrame->linesize);
avcodec_encode_video2(outVideoCodecContext, &outPacket, outFrame, &gotPicture);
if (gotPicture) {
if (outPacket.pts != AV_NOPTS_VALUE) {
outPacket.pts = av_rescale_q(outPacket.pts, videoSt->codec->time_base, videoSt->time_base);
}
if (outPacket.dts != AV_NOPTS_VALUE) {
outPacket.dts = av_rescale_q(outPacket.dts, videoSt->codec->time_base, videoSt->time_base);
}
//cout << "Write frame " << j++ << " (size = " << outPacket.size / 1000 << ")" << endl;
//cout << "(size = " << outPacket.size << ")" << endl;
//av_packet_rescale_ts(&outPacket, outVideoCodecContext->time_base, outAVFormatContext->streams[outVideoStreamIndex]->time_base);
//outPacket.stream_index = outVideoStreamIndex;
outFile << "outPacket->duration: " << outPacket.duration << ", " << "pAVPacket->duration: " << pAVPacket->duration << endl;
outFile << "outPacket->pts: " << outPacket.pts << ", " << "pAVPacket->pts: " << pAVPacket->pts << endl;
outFile << "outPacket.dts: " << outPacket.dts << ", " << "pAVPacket->dts: " << pAVPacket->dts << endl;
time_t timer;
double seconds;
mu.lock();
if (!activeMenu) {
time(&timer);
seconds = difftime(timer, startTime);
int h = (int)(seconds / 3600);
int m = (int)(seconds / 60) % 60;
int s = (int)(seconds) % 60;
std::cout << std::flush << "\r" << std::setw(2) << std::setfill('0') << h << ':'
<< std::setw(2) << std::setfill('0') << m << ':'
<< std::setw(2) << std::setfill('0') << s << std::flush;
}
mu.unlock();
write_lock.lock();
if (av_write_frame(outAVFormatContext, &outPacket) != 0) {
cerr << "Error in writing video frame" << endl;
}
write_lock.unlock();
av_packet_unref(&outPacket);
}
av_packet_unref(&outPacket);
av_free_packet(pAVPacket); //avoid memory saturation
}
}
}
outFile.close();
av_free(videoOutBuff);
return 0;
}

I resolved this problem performing an avformat_close_input(&inAudioFormatContext) before enter in pause, and an avformat_open_input(&inAudioFormatContext, "audio=Microfono (Realtek(R) Audio)", audioInputFormat, &audioOptions) after resume the recording. In this way the final file seems well syncronized with video.

Related

libusb failing at getting string descriptor on some devices

I am trying to get information about all attached devices.
This is my code:
libusb_device_descriptor desc;
libusb_config_descriptor *conDesc;
char szBuffer[256] = { 0 };
unsigned char strDesc[256];
libusb_device_handle *devHandle = NULL;
int retVal = 0;
__int64 i64Temp;
DWORD dwProdId;
DWORD dwProdId1;
i64Temp = 13888;
dwProdId = (DWORD)i64Temp;
retVal = libusb_open(dev, &devHandle);
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0)
{
cout << "failed to get device descriptor" << endl;
return;
}
r = libusb_get_config_descriptor(dev, 0, &conDesc);
printf("Interface Class = %d\n", conDesc->interface->altsetting->bInterfaceClass);
cout << "Number of possible configurations: " << (int)desc.bNumConfigurations << "" << endl;
cout << "Device Class: " << desc.bDeviceClass << endl;
cout << "Device Class: " << desc.bDeviceSubClass << endl;
printf("Class = %d\n", desc.bDeviceClass);
cout << "VendorID: " << desc.idVendor << endl;
cout << "ProductID: " << desc.idProduct << endl;
if (retVal == LIBUSB_SUCCESS)
{
retVal = libusb_get_string_descriptor_ascii(devHandle, desc.iManufacturer, strDesc, 256);
printf("Manufacturer: %s\n", strDesc);
retVal = libusb_get_string_descriptor_ascii(devHandle, desc.iSerialNumber, strDesc, 256);
printf("SerialNumber: %s\n", strDesc);
retVal = libusb_get_string_descriptor_ascii(devHandle, desc.iProduct, strDesc, 256);
printf("Product: %s\n", strDesc);
printf("\n\n");
}
else if (retVal != LIBUSB_SUCCESS)
{
printf("retVal failed");
printf("\n\n");
}
My code knows that there are 8 devices connected but it's getting manufacturer or serial number only on two of them. I would like to get this information for all of the attached devices.

Binaural beats in C++

I am trying to build a brain device using EEG input and outputting light pulses and binaural beats in "close to real-time" on a Raspberry PI. The light-output is no problem using WiringPi, but any audio output seems to be a major hurdle. The math of calculating a sinewave for a buffer is straightforward, but playing two frequencies on two channels via any standard libraries seems to be a very complicated process, and I can't come up with any relevant examples. I have successfully opened and closed an ALSA device thanks to this tutorial which complicates my fairly simple code tremendously but appears necessary for ALSA. I would be incredibly grateful if someone could show me the easiest method for playing two different calculated tones on left and right channels. The code below is the simplest ALSA playback example I could find.
#include <alsa/asoundlib.h>
#include <iostream>
using namespace std;
// Globals are generally a bad idea in code. We're using one here to keep it simple.
snd_pcm_t * _soundDevice;
bool Init(const char *name)
{
int i;
int err;
snd_pcm_hw_params_t *hw_params;
if( name == NULL )
{
// Try to open the default device
err = snd_pcm_open( &_soundDevice, "plughw:0,0", SND_PCM_STREAM_PLAYBACK, 0 );
}
else
{
// Open the device we were told to open.
err = snd_pcm_open (&_soundDevice, name, SND_PCM_STREAM_PLAYBACK, 0);
}
// Check for error on open.
if( err < 0 )
{
cout << "Init: cannot open audio device " << name << " (" << snd_strerror (err) << ")" << endl;
return false;
}
else
{
cout << "Audio device opened successfully." << endl;
}
// Allocate the hardware parameter structure.
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0)
{
cout << "Init: cannot allocate hardware parameter structure (" << snd_strerror (err) << ")" << endl;
return false;
}
if ((err = snd_pcm_hw_params_any (_soundDevice, hw_params)) < 0)
{
cout << "Init: cannot initialize hardware parameter structure (" << snd_strerror (err) << ")" << endl;
return false;
}
// Enable resampling.
unsigned int resample = 1;
err = snd_pcm_hw_params_set_rate_resample(_soundDevice, hw_params, resample);
if (err < 0)
{
cout << "Init: Resampling setup failed for playback: " << snd_strerror(err) << endl;
return err;
}
// Set access to RW interleaved.
if ((err = snd_pcm_hw_params_set_access (_soundDevice, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
{
cout << "Init: cannot set access type (" << snd_strerror (err) << ")" << endl;
return false;
}
if ((err = snd_pcm_hw_params_set_format (_soundDevice, hw_params, SND_PCM_FORMAT_S16_LE)) < 0)
{
cout << "Init: cannot set sample format (" << snd_strerror (err) << ")" << endl;
return false;
}
// Set channels to stereo (2).
if ((err = snd_pcm_hw_params_set_channels (_soundDevice, hw_params, 2)) < 0)
{
cout << "Init: cannot set channel count (" << snd_strerror (err) << ")" << endl;
return false;
}
// Set sample rate.
unsigned int actualRate = 44100;
if ((err = snd_pcm_hw_params_set_rate_near (_soundDevice, hw_params, &actualRate, 0)) < 0)
{
cout << "Init: cannot set sample rate to 44100. (" << snd_strerror (err) << ")" << endl;
return false;
}
if( actualRate < 44100 )
{
cout << "Init: sample rate does not match requested rate. (" << "44100 requested, " << actualRate << " acquired)" << endl;
}
// Apply the hardware parameters that we've set.
if ((err = snd_pcm_hw_params (_soundDevice, hw_params)) < 0)
{
cout << "Init: cannot set parameters (" << snd_strerror (err) << ")" << endl;
return false;
}
else
{
cout << "Audio device parameters have been set successfully." << endl;
}
// Get the buffer size.
snd_pcm_uframes_t bufferSize;
snd_pcm_hw_params_get_buffer_size( hw_params, &bufferSize );
// If we were going to do more with our sound device we would want to store
// the buffer size so we know how much data we will need to fill it with.
cout << "Init: Buffer size = " << bufferSize << " frames." << endl;
// Display the bit size of samples.
cout << "Init: Significant bits for linear samples = " << snd_pcm_hw_params_get_sbits(hw_params) << endl;
// Free the hardware parameters now that we're done with them.
snd_pcm_hw_params_free (hw_params);
// Prepare interface for use.
if ((err = snd_pcm_prepare (_soundDevice)) < 0)
{
cout << "Init: cannot prepare audio interface for use (" << snd_strerror (err) << ")" << endl;
return false;
}
else
{
cout << "Audio device has been prepared for use." << endl;
}
return true;
}
bool UnInit()
{
snd_pcm_close (_soundDevice);
cout << "Audio device has been uninitialized." << endl;
return true;
}
int main( char *argc, int argv )
{
Init(NULL);
UnInit();
return 0;
}
Use some up-to-date example, like this:
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
static const char *device = "default";
unsigned short buffer[2 * 24000];
int main(void)
{
int err;
snd_pcm_t *handle;
if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
printf("open error: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
}
if ((err = snd_pcm_set_params(handle,
SND_PCM_FORMAT_S16,
SND_PCM_ACCESS_RW_INTERLEAVED,
2, /* channels */
48000, /* rate */
1,
500000)) < 0) { /* buffer: 0.5 sec */
printf("open error: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
}
for (;;) {
for (int i = 0; i < 24000; i++) {
buffer[2 * i + 0] = 32767 * sin(...); /* left channel */
buffer[2 * i + 1] = 32767 * sin(...); /* right channel */
}
snd_pcm_sframes_t frames = snd_pcm_writei(handle, buffer, 24000);
if (frames < 0)
frames = snd_pcm_recover(handle, frames, 0);
if (frames < 0) {
printf("snd_pcm_writei failed: %s\n", snd_strerror(err));
break;
}
}
snd_pcm_close(handle);
return 0;
}

Can't send data to HID with libusb on windows

I'm currently trying to make a little piece of code that receive and send data to a HID (Texas Instrument HDK). There is no bug on the embedded system code (i can send data with a java program on mac OS to the device).
The reception is working but i can't send data (always getting error io return code).
Here's the code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include "libusb.h"
const static int PACKET_INT_LEN = 4;
const static int INTERFACE = 0;
const static int ENDPOINT_INT_IN = 0x83; /* endpoint 3 address for IN */
const static int ENDPOINT_INT_OUT = 0x04; /* endpoint 4 address for OUT */
const static int TIMEOUT = 5000;
#pragma comment(lib, "libusb-1.0.lib")
using namespace std;
libusb_device ** DoList();
libusb_device_handle * GetDevice(libusb_device ** deviceList);
int test_interrupt_transfer(libusb_device_handle * devh);
void error_interrupt_transfert(int r);
int main()
{
libusb_context ** context = NULL;
libusb_device_handle * deviceHandle = NULL;
int result_init = 0;
result_init = libusb_init(context);
if (result_init < 0)
cout << "Failed to init libusb." << endl;
else
deviceHandle = GetDevice(DoList());
int err = libusb_kernel_driver_active(deviceHandle, 0);
if (err >= LIBUSB_SUCCESS)
{
if (err == 1)
{
printf("Kernel driver is active, trying to detach");
err = libusb_detach_kernel_driver(deviceHandle, 0);
if (err != LIBUSB_SUCCESS)
{
printf("Error detaching interface from kernel");
}
}
}
if (libusb_kernel_driver_active(deviceHandle, 0) == 1)
{
if (libusb_detach_kernel_driver(deviceHandle, 0) == 0)
cout << "Kernel driver detatched !" << endl;
}
while (1)
{
test_interrupt_transfer(deviceHandle);
cout << 1 << endl;
Sleep(3000);
}
system("pause");
}
libusb_device ** DoList()
{
libusb_device **devs;
ssize_t count;
count = libusb_get_device_list(NULL, &devs);
if (count < 0)
{
cout << "Failed to get device list";
return NULL;
}
libusb_device *dev;
int i = 0;
cout << "Device list" << endl;
while ((dev = devs[i++]) != NULL)
{
struct libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0)
{
cout << "Failed to get device descriptor" << endl;
return NULL;
}
printf("\t%04x:%04x (bus %d, device %d)\n",
desc.idVendor, desc.idProduct,
libusb_get_bus_number(dev), libusb_get_device_address(dev));
}
return devs;
}
libusb_device_handle * GetDevice(libusb_device ** devList)
{
int i = 0,
vid = 0x1cbe,
pid = 0;
libusb_device * dev;
libusb_device_handle * handle = NULL;
unsigned char strDesc[256];
if (devList == NULL)
{
return NULL;
}
while ((dev = devList[i++]) != NULL)
{
struct libusb_device_descriptor desc;
struct libusb_config_descriptor ** conDesc = NULL;
int ret = libusb_get_device_descriptor(dev, &desc);
if (ret < 0)
{
cout << "Failed libusb_get_device_descriptor" << endl;
continue;
}
if (desc.idVendor == vid && desc.idProduct == pid)
{
int ret = libusb_open(dev, &handle);
if (ret < 0)
{
cout << "Failed libusb_open" << ret << endl;
break;
}
ret = libusb_claim_interface(handle, 0);
if (ret < 0)
{
cout << "Failed libusb_claim_interface" << endl;
libusb_close(handle);
handle = NULL;
break;
}
libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, strDesc, 256);
printf(" Manufacturer = %s\n", strDesc);
libusb_get_string_descriptor_ascii(handle, desc.iProduct, strDesc, 256);
printf(" Product = %s\n", strDesc);
libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, strDesc, 256);
printf(" Serial number = %s\n", strDesc);
break;
}
}
cout << "Success openning device" << endl;
libusb_free_device_list(devList, 1);
return handle;
}
int test_interrupt_transfer(libusb_device_handle * devh)
{
int r, i;
int transferred = 0;
int * ptransferred = &transferred;
unsigned char answer[PACKET_INT_LEN];
unsigned char question[2];
r = libusb_interrupt_transfer(devh, ENDPOINT_INT_OUT, question,
sizeof(question), ptransferred, TIMEOUT);
if (r < 0) {
error_interrupt_transfert(r);
return r;
}
r = libusb_interrupt_transfer(devh, ENDPOINT_INT_IN, answer, PACKET_INT_LEN,
&transferred, TIMEOUT);
if (r < 0)
{
error_interrupt_transfert(r);
return r;
}
for (i = 0; i < PACKET_INT_LEN; i++)
{
printf("%02x; ", answer[i]);
}
printf("\n");
return 0;
}
void error_interrupt_transfert(int r)
{
switch (r)
{
case LIBUSB_SUCCESS: cout << "Success" << endl;
break;
case LIBUSB_ERROR_TIMEOUT: cout << "Timeout" << endl;
break;
case LIBUSB_ERROR_PIPE: cout << "Error pipe" << endl;
break;
case LIBUSB_ERROR_OVERFLOW: cout << "Overflow" << endl;
break;
case LIBUSB_ERROR_NO_DEVICE: cout << "No device" << endl;
break;
case LIBUSB_ERROR_IO: cout << "Error IO" << endl;
break;
case LIBUSB_ERROR_NOT_FOUND: cout << "Not found" << endl;
break;
case LIBUSB_ERROR_INVALID_PARAM: cout << "Invalid param" << endl;
break;
case LIBUSB_ERROR_ACCESS: cout << "Error access" << endl;
break;
case LIBUSB_ERROR_INTERRUPTED: cout << "Interrupted" << endl;
break;
case LIBUSB_ERROR_BUSY: cout << "Busy" << endl;
break;
case LIBUSB_ERROR_NO_MEM: cout << "No memory" << endl;
break;
case LIBUSB_ERROR_NOT_SUPPORTED: cout << "Not supported" << endl;
break;
case LIBUSB_ERROR_OTHER: cout << "Other" << endl;
break;
default: cout << "Unknow error code" << r << endl;
}
}
Any idea folks?
Calmant Kévin

server freezes when handling large messages in simple server c++

I have a client and server running, and it seems to run great, until I either a really large message, or a partial message. In either of those events it freezes. The buffer is set to 1024, but changing it doesn't seem to affect the message at all. I've copied the getRequest function where it freezes below.
If anyone knows why it freezes or how to deal with large and partial messages, that would be great, thanks.
It freezes on the line int nread = (client, buf_,1024,0); Any solutions?
cout << "entered get request while loop" << endl;
int nread = recv(client,buf_,1024,0);
cout << "number read: " << nread << endl;
string
Server::get_request(int client) {
cout << "getting request" << endl;
string request = "";
// read until we get a newline
while (cache.find("\n") == string::npos) {
cout << "entered get request while loop" << endl;
int nread = recv(client,buf_,1024,0);
if (nread < 0) {
if (errno == EINTR)
// the socket call was interrupted -- try again
continue;
else
// an error occurred, so break out
return "";
} else if (nread == 0) {
// the socket is closed
return "";
}
// be sure to use append in case we have binary data
cache.append(buf_,nread);
cout << "cache: " << cache << " : " << endl;
}
int position = cache.find("\n");
if (position == -1){
request = cache;
cache = "";
}
else{
cout << "Cache position: " << position << endl;
request = cache.substr(0,position+1);
cache.erase(0,position+1);
}
cout << "request: " << request << " : " << endl;
return request;
}
This is the full server.cc file
#include "server.h"
#include <vector>
#include <map>
#include <sstream>
#include <iostream>
Server::Server(int port) {
// setup variables
port_ = port;
buflen_ = 1024;
buf_ = new char[buflen_+1];
// cache = "";
}
Server::~Server() {
delete[] buf_;
users.clear();
}
void
Server::run() {
// create and run the server
create();
serve();
}
void
Server::create() {
struct sockaddr_in server_addr;
// setup socket address structure
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port_);
server_addr.sin_addr.s_addr = INADDR_ANY;
// create socket
server_ = socket(PF_INET,SOCK_STREAM,0);
if (!server_) {
perror("socket");
exit(-1);
}
// set socket to immediately reuse port when the application closes
int reuse = 1;
if (setsockopt(server_, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
perror("setsockopt");
exit(-1);
}
// call bind to associate the socket with our local address and
// port
if (bind(server_,(const struct sockaddr *)&server_addr,sizeof(server_addr)) < 0) {
perror("bind");
exit(-1);
}
// convert the socket to listen for incoming connections
if (listen(server_,SOMAXCONN) < 0) {
perror("listen");
exit(-1);
}
}
void
Server::close_socket() {
close(server_);
}
void
Server::serve() {
// setup client
int client;
struct sockaddr_in client_addr;
socklen_t clientlen = sizeof(client_addr);
// accept clients
while ((client = accept(server_,(struct sockaddr *)&client_addr,&clientlen)) > 0) {
handle(client);
}
close_socket();
}
Server::Message Server::parse_request(string request){
stringstream ss;
istringstream istr(request);
Message message;
message.needed = false;
message.valid = true;
message.user = "";
message.index = -1;
// istream_iterator<string> be
istr >> message.command;
//message.command = ss.str();
cout << "got command:" << message.command << ":" << endl;
if(message.command == "put")
{
istr >> message.user;
//ss << istr;
istr >> message.subject;
istr >> message.length;
cout << "message.length = " << message.length <<endl;
message.needed = false;
}
else if (message.command == "list"){
istr >> message.user;
message.needed = false;
message.length = 0;
}
else if (message.command == "get"){
istr >> message.user;
istr >> message.index;
message.needed = false;
message.length = 0;
}
else if (message.command == "reset"){
message.needed = false;
message.length = 0;
}
else{
cout << "I don't recognize that request.";
message.valid = false;
}
return message;
}
void Server::get_value(int client, Message message){
//call recv until all bytes needed are recieved
while(message.needed){
int nread = recv(client,buf_,1024,0);
if (nread < 0) {
if (errno == EINTR)
// the socket call was interrupted -- try again
continue;
else
// an error occurred, so break out
return;
} else if (nread == 0) {
// the socket is closed
return;
}
cache.append(buf_,nread);
cout << "cache length " << cache.size();
if(message.length <= cache.size()){
cout << "Message value " << message.value;
cout << "cache length " << cache.size();
message.needed = false;
message.value = cache.substr(0,message.length);
cache.erase(0,message.length);
cout << "Message value " << message.value;
cout << "cache length " << cache.size();
}
}
}
string
Server::get_request(int client) {
cout << "getting request" << endl;
string request = "";
// read until we get a newline
while (cache.find("\n") == string::npos) {
cout << "entered get request while loop" << endl;
int nread = recv(client,buf_,1024,0);
if (nread < 0) {
if (errno == EINTR)
// the socket call was interrupted -- try again
continue;
else
// an error occurred, so break out
return "";
} else if (nread == 0) {
// the socket is closed
return "";
}
// be sure to use append in case we have binary data
cache.append(buf_,nread);
cout << "cache: " << cache << " : " << endl;
}
int position = cache.find("\n");
// int position = 0;
// while (cache.find("/n") == string::npos)
// {
// position++;
// }
if (position == -1){
request = cache;
cache = "";
}
else{
cout << "Cache position: " << position << endl;
request = cache.substr(0,position+1);
cache.erase(0,position+1);
}
cout << "request: " << request << " : " << endl;
// a better server would cut off anything after the newline and
// save it in a cache
return request;
}
bool Server::send_response(int client, string response) {
// prepare to send response
cout << "sending response:" << response << ":" << endl;
const char* ptr = response.c_str();
int nleft = response.length();
int nwritten;
// loop to be sure it is all sent
while (nleft) {
if ((nwritten = send(client, ptr, nleft, 0)) < 0) {
if (errno == EINTR) {
// the socket call was interrupted -- try again
continue;
} else {
// an error occurred, so break out
perror("write");
return false;
}
} else if (nwritten == 0) {
// the socket is closed
return false;
}
nleft -= nwritten;
ptr += nwritten;
cout << "number written: " << nwritten << endl;
}
cout << "finished sending response " << endl;
return true;
}
bool Server::handle_response(int client, Message message) {
cout << "handling response" << endl;
bool success = false;
if(message.command == "put"){
if(message.length == 0){
return false;
}
message.value = cache.substr(0,message.length);
cache.erase(0,message.length);
if(subjects.count(message.user) == 0){
vector<string> userSubjects;
subjects[message.user] = userSubjects;
}
subjects[message.user].push_back(message.subject);
if(users.count(message.user) == 0){
vector<Message> messages;
users[message.user] = messages;
}
users[message.user].push_back(message);
// users.insert(message.user, message.subject);
cout << "sending response to client" << endl;
success = send_response(client, "OK\n");
}
else if("list" == message.command){
if(message.user == ""){
return false;
}
vector<string> currentSubjects = subjects[message.user];
cout << "subjects for message.user: " << message.user << endl;
stringstream sstream;
sstream << "list " << currentSubjects.size() << "\n";
//success = send_response(client, sstream.str());
// if(success == false){
// return false;
// }
// cout << "client sent user" << endl;
for (int i=0; i<currentSubjects.size(); i++){
// stringstream sstm;
sstream << (i+1) << " " << currentSubjects[i] << "\n";
}
success = send_response(client, sstream.str());
if(success == false){
return false;
}
// success = true;
cout << "message list sent successfully" << endl;
}
else if (message.command == "get"){
if(message.index == -1){
return false;
}
if(message.user == ""){
return false;
}
vector<Message> currentMessages = users[message.user];
if(message.index > currentMessages.size()){
return false;
}
stringstream sstm;
for (int i=0; i<currentMessages.size(); i++){
if ((i+1) == message.index){
sstm << "message " << currentMessages[i].subject << " " << currentMessages[i].length << "\n" << currentMessages[i].value;
cout << "message.value = " << currentMessages[i].value << endl;
}
}
cout << "message to send " << sstm.str() << endl;
success = send_response(client, sstm.str());
if(success == false){
return false;
}
// success = true;
}
else if (message.command == "reset"){
users.clear();
subjects.clear();
success = send_response(client, "OK\n");
// success = true;
}
else {
debug = true;
if (debug == true){
cout << "Debug message: " << "No valid command found in handle" << endl;
}
}
return success;
}
void
Server::handle(int client) {
// loop to handle all requests
while (1) {
// get a request
cout << "looking for new request" << endl;
string request = get_request(client);
cout << "request = " << request << endl;
// break if client is done or an error occurred
if (request.empty()) {
cout << "empty request" << endl;
break;
}
cout << "request:" << request << ":" << endl;
//parse
Message message = parse_request(request);
cout << "finished parsing" << endl;
if(message.valid == false){
cout << "invalid message" << endl;
send_response(client, "error unrecognized command\n");
cout << "cache after break from bad command: " << cache << endl;
continue;
}
if(message.length > cache.size()){
message.needed = true;
cout << "message length greater than cache size" << endl;
cout << "cache.size = " << cache.size() << endl;
}
if(message.needed){
get_value(client, message);
}
// handle message
bool success = handle_response(client, message);
cout << "finished handling response" << endl;
cout << "cache after handle: " << cache << " : " << endl;
// break if an error occurred
if (!success) {
cout << "error handling request" << endl;
send_response(client, "error handling request\n");
continue;
}
cout << "end of request" << endl;
}
close(client);
}

Decoding audio with FFMPEG

I am using FFMPEG to decode an audio file, but I am not able to do it.
AVFormatContext *pFormatCtx;
AVCodec *pCodec_audio;
AVCodecContext *aCodecCtx_audio = NULL;
AVPacket packet;
string outfilename = "salida.avi";
string filename = "john.wav";
int audioStream;
int out_size, len, size;
FILE *outfile;
int16_t *outbuf;
uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
avcodec_init();
/* register all the codecs */
av_register_all();
if(av_open_input_file(&pFormatCtx, filename.c_str(), NULL, 0, NULL) != 0) {
cerr << "Archivo no encontrado" << endl;
return -1; // Couldn't open file
}
if(av_find_stream_info(pFormatCtx) < 0) {
cerr << " No encontro el stream de info" << endl;
return -1;// Couldn't find stream information
}
dump_format(pFormatCtx, 0, filename.c_str(), 0);
for(unsigned int i=0; i < pFormatCtx->nb_streams; i++)
if(pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO)
audioStream = i;
aCodecCtx_audio = pFormatCtx->streams[audioStream]->codec;
pCodec_audio = avcodec_find_decoder(aCodecCtx_audio->codec_id);
if(pCodec_audio == NULL) {
cerr<< "Unsupported codec!" << endl;
return -1; // Codec not found
}
if(avcodec_open(aCodecCtx_audio, pCodec_audio) < 0) {
cerr << "No se pudo abrir el codec de audio" << endl;
return -1;
}
outbuf = (int16_t*) av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
outfile = fopen(outfilename.c_str(), "wb");
if (!outfile) {
exit(1);
}
av_init_packet(&packet);
packet.data = inbuf;
while(av_read_frame(pFormatCtx, &packet) == 0) {
if(packet.stream_index == audioStream) {
size = packet.size;
if (size == 0) {
cerr << "Size = 0 " << endl;
break;
}
while(size > 0) {
out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
len = avcodec_decode_audio3(aCodecCtx_audio, outbuf, &out_size , &packet);
//av_free_packet(&packet);
cout << len << endl;
if(len == -1) {
cerr << "Error while decoding" << endl;
return 1;
}
if(out_size > 0) {
fwrite(outbuf, 1, out_size, outfile);
}
size -= len;
packet.data += len;
}
}
}
av_free_packet(&packet);
fclose(outfile);
free(outbuf);
cout << "END CODE" << endl;
avcodec_close(aCodecCtx_audio);
av_free(aCodecCtx_audio);
In the code I am trying to decode an .wav file to a .avi file. The output file ("salida.avi") is created , but does not play.