My version of FFmpeg is 4.4.
There is a logic in my code that calls avformat_find_stream_info() twice continuously, but I don't understand why it crashed here. I tried single-step debugging but it didn't work out. Here is my simply code that can be run directly:
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
int main()
{
av_log_set_level(AV_LOG_DEBUG);
const char* in_filename_a = "aoutput.aac";
AVFormatContext* ifmt_ctx_a = NULL;
int ret = avformat_open_input(&ifmt_ctx_a, in_filename_a, 0, 0);
if (ret < 0)
{
fprintf(stderr, "Could not open input_a %s", in_filename_a);
return -1;
}
fprintf(stderr, "before ifmt_ctx_a=0x%x\n", ifmt_ctx_a->streams[0]);
ret = avformat_find_stream_info(ifmt_ctx_a, 0);
if (ret < 0)
{
fprintf(stderr, "Could not find input_a stream info");
return -1;
}
fprintf(stderr, "after ifmt_ctx_a=0x%x\n", ifmt_ctx_a->streams[0]);
/// crashed here
ret = avformat_find_stream_info(ifmt_ctx_a, 0);
if (ret < 0)
{
fprintf(stderr, "Could not find input_a stream info");
return -1;
}
}
There are few hints that imply that we shouldn't execute avformat_find_stream_info twice.
The documentation says: "examined packets may be buffered for later processing."
There is a change that the first execution buffers few packets, and the second execution tries to buffer the packets again without allocating additional space.
The console prints logging messages as:
Before avformat_find_stream_info() pos: 0 bytes read:65696 seeks:4 nb_streams:1
After avformat_find_stream_info() pos: 27420 bytes read:65696 seeks:4 frames:50
The messages imply that the position advances from 0 to 27420. The address of ifmt_ctx_a->streams[0] is the same, but the execution of the first avformat_find_stream_info did some seeking (so the second execution is not the same as the first one).
Using the debugger, we can see that ifmt_ctx_a->pb[0].buf_ptr is increased after the first execution of avformat_find_stream_info.
Note:
I don't know if the crash is normal behavior or a bug in Libavformat library.
I didn't try looking at the source code of Libavformat.
For reading twice, you may close and reopen ifmt_ctx_a:
avformat_close_input(&ifmt_ctx_a);
ret = avformat_open_input(&ifmt_ctx_a, in_filename_a, 0, 0);
I don't see any reason to do that...
Other option is opening another AVFormatContext:
AVFormatContext* ifmt_ctx_a = NULL;
int ret = avformat_open_input(&ifmt_ctx_a, in_filename_a, 0, 0);
if (ret < 0)
{
fprintf(stderr, "Could not open input_a %s", in_filename_a);
return -1;
}
ret = avformat_find_stream_info(ifmt_ctx_a, NULL);
if (ret < 0)
{
fprintf(stderr, "Could not find input_a stream info");
return -1;
}
//Opening another AVFormatContext:
////////////////////////////////////////////////////////////////////////////
AVFormatContext* ifmt_ctx_a2 = NULL;
ret = avformat_open_input(&ifmt_ctx_a2, in_filename_a, 0, 0);
if (ret < 0)
{
fprintf(stderr, "Could not open input_a %s", in_filename_a);
return -1;
}
ret = avformat_find_stream_info(ifmt_ctx_a2, NULL);
if (ret < 0)
{
fprintf(stderr, "Could not find input_a stream info");
return -1;
}
////////////////////////////////////////////////////////////////////////////
Related
My ultimate goal will be to split multi channel WAV files into single mono ones, after few days of experiments my plan is the sequence:
Decode audio file into a frame.
Convert interleaved frame into a planar one. (in order to separate the data buffer into multiple ones)
Grab the planar frame buffers and encode each of them into a new file.
So far I'm stuck trying to convert a wav file from interleaved to a planar one, and reprint the wav file.
edit:
I've turned on guard malloc and apparently the error is within the convert function
Here's the code:
AVCodecContext* initializeAndOpenCodecContext(AVFormatContext* formatContext, AVStream* stream){
// grab our stream, most audio files only have one anyway
const AVCodec* decoder = avcodec_find_decoder(stream->codecpar->codec_id);
if (!decoder){
std::cout << "no decoder, can't go ahead!\n";
return nullptr;
}
AVCodecContext* codecContext = avcodec_alloc_context3(decoder);
avcodec_parameters_to_context(codecContext, stream->codecpar);
int err = avcodec_open2(codecContext, decoder, nullptr);
if (err < 0){
std::cout << "couldn't open codex!\n";
}
return codecContext;
}
void initialiseResampler(SwrContext* resampler, AVFrame* inputFrame, AVFrame* outputFrame){
av_opt_set_chlayout(resampler, "in_channel_layout", &inputFrame->ch_layout, 0);
av_opt_set_chlayout(resampler, "out_channel_layout", &outputFrame->ch_layout, 0);
av_opt_set_int(resampler, "in_sample_fmt", inputFrame->format, 0);
av_opt_set_int(resampler, "out_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
av_opt_set_int(resampler, "in_sample_rate", inputFrame->sample_rate, 0);
av_opt_set_int(resampler, "out_sample_rate", outputFrame->sample_rate, 0);
}
AVFrame* initialisePlanarFrame(AVFrame* frameToInit, AVFrame* inputFrame){
//AVFrame *planar_frame = av_frame_alloc();
frameToInit->nb_samples = inputFrame->nb_samples;
frameToInit->ch_layout = inputFrame->ch_layout;
frameToInit->format = AV_SAMPLE_FMT_FLTP;
frameToInit->sample_rate = inputFrame->sample_rate;
return nullptr;
}
int main() {
AVCodecContext *codingContext= NULL;
const AVCodec *codec;
codec = avcodec_find_encoder(AV_CODEC_ID_PCM_F32LE);
codingContext = avcodec_alloc_context3(codec);
codingContext->bit_rate = 16000;
codingContext->sample_fmt = AV_SAMPLE_FMT_FLT;
codingContext->sample_rate = 48000;
codingContext->ch_layout.nb_channels = 2;
codingContext->ch_layout.order = (AVChannelOrder)0;
uint8_t **buffer_ = NULL;
AVFrame* planar_frame = NULL;
// open input
AVFormatContext* formatContext = nullptr;
int err = avformat_open_input(&formatContext, "/Users/tonytorm/Desktop/drum kits/DECAP - Drums That Knock Vol. 9/Kicks/Brash Full Metal Kick.wav", nullptr, nullptr);
if (err < 0){
fprintf(stderr, "Unable to open file!\n");
return;
}
// find audio stream
err = avformat_find_stream_info(formatContext, nullptr);
if (err > 0){
fprintf(stderr, "Unable to retrieve stream info!\n");
return;
}
int index = av_find_best_stream(formatContext, AVMEDIA_TYPE_AUDIO, -1, -1, nullptr, 0);
if (index < 0){
std::cout<< "coudn't find audio stream in this file" << '\n';
}
AVStream* stream = formatContext->streams[index];
auto fileName = "/Users/tonytorm/Desktop/newFile.wav";
FILE* newFile = fopen(fileName, "w+");
// find right codec and open it
if (auto openCodecContext = initializeAndOpenCodecContext(formatContext, stream)){
AVPacket* packet = av_packet_alloc();
AVFrame* frame = av_frame_alloc();
AVFrame* planar_frame = av_frame_alloc();
SwrContext *avr = swr_alloc(); //audio resampling context
AVChannelLayout monoChannelLayout{(AVChannelOrder)0};
monoChannelLayout.nb_channels = 2;
while (!av_read_frame(formatContext, packet)){
if (packet->stream_index != stream->index) continue; // we only care about audio
int ret = avcodec_send_packet(openCodecContext, packet);
if ( ret < 0) {
if (ret != AVERROR(EAGAIN)){ // if error is actual error not EAGAIN
std::cout << "can't do shit\n";
return;
}
}
while (int bret = avcodec_receive_frame(openCodecContext, frame) == 0){
initialisePlanarFrame(planar_frame, frame);
int buffer_size_in = av_samples_get_buffer_size(nullptr,
frame->ch_layout.nb_channels,
frame->nb_samples,
(AVSampleFormat)frame->format,
0);
int buffer_size_out = buffer_size_in/frame->ch_layout.nb_channels;
//planar_frame->linesize[0] = buffer_size_out;
int ret = av_samples_alloc(planar_frame->data,
NULL,
planar_frame->ch_layout.nb_channels,
planar_frame->nb_samples,
AV_SAMPLE_FMT_FLTP,
0);
initialiseResampler(avr, frame, planar_frame);
if (int errRet = swr_init(avr) < 0) {
fprintf(stderr, "Failed to initialize the resampling context\n");
}
if (ret < 0){
char error_message[AV_ERROR_MAX_STRING_SIZE];
av_strerror(ret, error_message, AV_ERROR_MAX_STRING_SIZE);
fprintf(stderr, "Error allocating sample buffer: %s\n", error_message);
return -1;
}
int samples_converted = swr_convert(avr,
planar_frame->data,
buffer_size_out,
(const uint8_t **)frame->data,
buffer_size_in);
if (samples_converted < 0) {
// handle error
std::cout << "error in conversion\n";
return;
}
if (avcodec_open2(codingContext, codec, NULL) < 0) {
std::cout << "can't encode!\n";
return;
}
AVPacket* nu_packet = av_packet_alloc();
while (int copy = avcodec_send_frame(codingContext, planar_frame) != 0){
if (copy == AVERROR(EAGAIN) || copy == AVERROR_EOF){
std::cout << "can't encode file\n";
return;
}
if (avcodec_receive_packet(codingContext, nu_packet) >=0){
fwrite(nu_packet->data, 4, nu_packet->size, newFile);
//av_write_frame(avc, nu_packet);
}
}
av_freep(planar_frame->data);
av_frame_unref(frame);
av_frame_unref(planar_frame);
}
// av_packet_free(&packet);
// av_packet_free(&nu_packet);
}
swr_free(&avr);
avcodec_free_context(&codingContext);
}
fclose(newFile);
}
I know i should write a header to the new wave file but for now I'm just trying to write the raw audio data. I'm getting always the same error but in different parts of the code (randomly), sometimes the code even compiles (writing the raw audio data, but filling it with some rubbish as well, i end up with a data file that is thrice the original one, sometimes i end up with a slightly smaller file - i guess the raw audio without the headers), results are basically random.
Here are some of the functions that trigger the error:
int ret = av_samples_alloc(); //(this the most common one)
swr_convert()
av_freep();
the error is:
main(64155,0x101b5d5c0) malloc: Incorrect checksum for freed object 0x106802600: probably modified after being freed.
Corrupt value: 0x0
main(64155,0x101b5d5c0) malloc: *** set a breakpoint in malloc_error_break to debug */
I'm trying to sniff all TCP SYN packets received by any of my network adapters and I treid doing so by using the free npcap library available online.
You can see my code below
pcap_if_t* allNetworkDevices;
std::vector<pcap_t*> networkInterfacesHandles;
std::vector<WSAEVENT> sniffEvents;
void packet_handler(u_char* user, const struct pcap_pkthdr* header, const u_char* packet) {
cout << "here" << endl;
}
BOOL openAllInterfaceHandles()
{
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t* curNetworkHandle;
if (pcap_findalldevs(&allNetworkDevices, errbuf) == -1) {
printf("Error in pcap_findalldevs: %s\n", errbuf);
return FALSE;
}
for (pcap_if_t* d = allNetworkDevices; d != NULL; d = d->next) {
//curNetworkHandle = pcap_open(d->name, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf);
printf("%s\n", d->description);
curNetworkHandle = pcap_open_live(d->name, BUFSIZ, 1, 1000, errbuf);
if (curNetworkHandle == NULL) {
printf("Couldn't open device %s: %s\n", d->name, errbuf);
continue;
}
networkInterfacesHandles.push_back(curNetworkHandle);
// Compile and set the filter
struct bpf_program fp;
char filter_exp[] = "(tcp[tcpflags] & tcp-syn) != 0";
if (pcap_compile(curNetworkHandle, &fp, filter_exp, 1, PCAP_NETMASK_UNKNOWN) < 0) {
printf("Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(curNetworkHandle));
continue;
}
if (pcap_setfilter(curNetworkHandle, &fp) == -1) {
printf("Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(curNetworkHandle));
continue;
}
// Create an event for the handle
sniffEvents.push_back(pcap_getevent(curNetworkHandle));
}
}
int main()
{
openAllInterfaceHandles();
while (TRUE)
{
DWORD result = WaitForMultipleObjects(sniffEvents.size(), sniffEvents.data(), FALSE, INFINITE);
if (result == WAIT_FAILED) {
printf("Error in WaitForMultipleObjects: %d\n", GetLastError());
break;
}
// Dispatch packets for the handle associated with the triggered event
int index = result - WAIT_OBJECT_0;
pcap_dispatch(networkInterfacesHandles[index], -1, &packet_handler, NULL);
if (cond)
{
cout << "done" << endl;
break;
}
}
while (!networkInterfacesHandles.empty())
{
pcap_close(networkInterfacesHandles.back());
networkInterfacesHandles.pop_back();
}
pcap_freealldevs(allNetworkDevices);
return 0;
}
cond is some condition I'm using which is irrelevant to the problem.
For some reason it won't go into the packet_handler even when I receive TCP SYN packets (which I check by using Wireshark) and I tried sending them either via the loopback and also from another PC in the same LAN.
Any help to find the problem would be greatly appreciated.
There are some tutorials on the internet about it, most of them is using deprecated functions and unfortunately the API use to broke and it makes a mess and I'm really confused.
I'm following tutorials, learning with the documentation and seeing the examples of the current version (even that way some examples does not work).
What I'm trying to do is to save frames in .png, following the examples and reading I did this, but I'm confused about the conversion the frame to RBG and saving it:
#include <iostream>
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
}
int main(int argc, char ** argv)
{
if (argc < 2)
{
av_log(0, AV_LOG_FATAL, "Usage: %s <input>", argv[0]);
return -1;
}
const char * filename = argv[1];
// register all codecs and formats
av_register_all();
// open input file, and allocate format context
AVFormatContext *avFormatContext = avformat_alloc_context();
if (avformat_open_input(&avFormatContext, filename, 0, 0) < 0)
{
av_log(0, AV_LOG_FATAL, "Could not open source file %s", filename);
return -1;
}
// retrieve stream information
if (avformat_find_stream_info(avFormatContext, 0) < 0)
{
av_log(0, AV_LOG_FATAL, "Could not find stream information");
return -1;
}
// dump information about file onto standard error
av_dump_format(avFormatContext, 0, filename, 0);
// find the "best" video stream in the file.
int result = av_find_best_stream(avFormatContext, AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0);
if (result < 0)
{
av_log(0, AV_LOG_FATAL, "Could not find %s stream in input file '%s'", av_get_media_type_string(AVMEDIA_TYPE_VIDEO), filename);
return -1;
}
int stream = result;
AVStream *avStream = avFormatContext->streams[stream];
AVCodecContext *avCodecContext = avStream->codec;
// find decoder for the stream
AVCodec *avCodec = avcodec_find_decoder(avCodecContext->codec_id);
if (! avCodec)
{
av_log(0, AV_LOG_FATAL, "Failed to find %s codec", av_get_media_type_string(AVMEDIA_TYPE_VIDEO));
return -1;
}
// init the decoders, with reference counting
AVDictionary *avDictionary = 0;
av_dict_set(&avDictionary, "refcounted_frames", "1", 0);
if (result = avcodec_open2(avCodecContext, avCodec, &avDictionary) < 0)
{
av_log(0, AV_LOG_FATAL, "Failed to open %s codec", av_get_media_type_string(AVMEDIA_TYPE_VIDEO));
return -1;
}
AVFrame *avFrame = av_frame_alloc();
if (! avFrame)
{
av_log(0, AV_LOG_FATAL, "Could not allocate frame");
return -1;
}
// initialize packet, set data to null, let the demuxer fill it
AVPacket avPacket;
av_init_packet(&avPacket);
avPacket.data = 0;
avPacket.size = 0;
while (av_read_frame(avFormatContext, &avPacket) >= 0)
{
if (avPacket.stream_index == stream)
{
int success = avcodec_decode_video2(avCodecContext, avFrame, &success, &avPacket);
if (success <= 0)
{
av_log(0, AV_LOG_FATAL, "Error decoding video frame");
return -1;
}
// ... saving...
}
}
avcodec_close(avCodecContext);
avformat_close_input(&avFormatContext);
av_frame_free(&avFrame);
return 0;
}
I'm working with some C++ socket examples. The client run and can connect to the server but can't send the file. I think there's a problem with the send() but I can't fix it.Edit: the error message is "connection reset by peer"
Any ideas are welcomed.
I use OpenSuSE with QT 4.7.4
Here's the send and receive function
void str_server(int sock)
{
char buf[1025];
const char* filename = "//home//romanov//Documents//HelloWorld-build-desktop-Qt_4_7_4_in_PATH__System__Release//ss.png";
FILE *file = fopen(filename, "rb");
if (!file)
{
cerr<<"Can't open file for reading";
return;
}
while (!feof(file))
{
int rval = fread(buf, 1, sizeof(buf), file);//read value
if (rval < 1)
{
cerr<<"Can't read from file";
fclose(file);
return;
}
int off = 0;
do
{
int sent = send(sock, &buf[off], rval - off, 0);
if (sent < 1)
{
// if the socket is non-blocking, then check
// the socket error for WSAEWOULDBLOCK/EAGAIN
// (depending on platform) and if true then
// use select() to wait for a small period of
// time to see if the socket becomes writable
// again before failing the transfer...
cout<<"Can't write to socket";
fclose(file);
return;
}
off += sent;
}
while (off < rval);
}
fclose(file);
}
//===================
void RecvFile(int winsock)
{
int rval;
char buf[1025];
FILE *file = fopen("//home//romanov//Documents//HelloWorld-build-desktop-Qt_4_7_4_in_PATH__System__Release//ss2.png", "wb");
if (!file)
{
printf("Can't open file for writing");
return;
}
do
{
rval = recv(winsock, buf, sizeof(buf), 0);
if (rval < 0)
{
// if the socket is non-blocking, then check
// the socket error for WSAEWOULDBLOCK/EAGAIN
// (depending on platform) and if true then
// use select() to wait for a small period of
// time to see if the socket becomes readable
// again before failing the transfer...
printf("Can't read from socket");
fclose(file);
return;
}
if (rval == 0)
break; //line 159
int off = 0;
do
{
int written = fwrite(&buf[off], 1, rval - off, file);
if (written < 1)
{
printf("Can't write to file");
fclose(file);
return;
}
off += written;
}
while (off < rval);
} //line 175
while (1);
fclose(file);
}
Well , the problem is my bad, I read the wrong socket in the recvFile() , if you guys encounter the same problem, you should check it out.
I'm learning some examples about C++ socket. One of the code here has an error : "expect token while got fclose" at the line above the last line
The code seems fine with me, so I can't figure out what is wrong here.
Any ideas are appreciated.
void RecvFile(int sock, const char* filename)
{
int rval;
char buf[0x1000];
FILE *file = fopen(filename, "wb");
if (!file)
{
printf("Can't open file for writing");
return;
}
do
{
rval = recv(sock, buf, sizeof(buf), 0);
if (rval < 0)
{
// if the socket is non-blocking, then check
// the socket error for WSAEWOULDBLOCK/EAGAIN
// (depending on platform) and if true then
// use select() to wait for a small period of
// time to see if the socket becomes readable
// again before failing the transfer...
printf("Can't read from socket");
fclose(file);
return;
}
if (rval == 0)
break;
int off = 0;
do
{
int written = fwrite(&buf[off], 1, rval - off, file);
if (written < 1)
{
printf("Can't write to file");
fclose(file);
return;
}
off += written;
}
while (off < rval);
}
fclose(file);
}
You have a do with no corresponding while:
do
{
// ...
do
{
// ...
}
while (off < rval);
}
// No while here
fclose(file);
It appears that it should just be while (true), which you might as well just stick at the top, instead of doing a do while. Execution will break from the loop if recv returns 0 or less, which indicate an orderly shutdown and an error respectively. So change it to:
while (true)
{
// ...
do
{
// ...
}
while (off < rval);
}
fclose(file);
You have a do statement without a corresponding while:
do // <== THERE IS NO CORRESPONDING while FOR THIS do
{
rval = recv(sock, buf, sizeof(buf), 0);
if (rval < 0)
{
// ...
}
// ...
do
{
// ...
}
while (off < rval); // <== This is OK: the "do" has a matching "while"
}
// Nothing here! Should have a "while (condition)"
If you just want to repeat your loop indefinitely, then you should use while (true) - either replacing the do keyword (preferably), or adding it where the missing while should go (as indicated by the above comments).
You started a do without actually supplying a while();
do
{
rval = recv(sock, buf, sizeof(buf), 0);
if (rval < 0)
{
// if the socket is non-blocking, then check
// the socket error for WSAEWOULDBLOCK/EAGAIN
// (depending on platform) and if true then
// use select() to wait for a small period of
// time to see if the socket becomes readable
// again before failing the transfer...
printf("Can't read from socket");
fclose(file);
return;
}
if (rval == 0)
break;
int off = 0;
do
{
int written = fwrite(&buf[off], 1, rval - off, file);
if (written < 1)
{
printf("Can't write to file");
fclose(file);
return;
}
off += written;
}
while (off < rval);
} //while() Needs to go here
fclose(file);