libjpeg jpeg_stdio_dest() seg fault - c

Hello I have a little problem with writting data to jpeg:
Here is the code snippet:
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
/* More stuff */
FILE * outfile; /* target file */
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
int row_stride; /* physical row width in image buffer */
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
if ((outfile = fopen(filename, "wb+")) == NULL) {
fprintf(stderr, "can't open %s\n", filename);
exit(1);
}
else
printf("File successfully opened\n");
jpeg_stdio_dest(&cinfo, outfile);
cinfo.image_width = img_w;
cinfo.image_height = img_h;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
It gives me a segfault on jpeg_stdio_dest, gdb output:
#0 0x00007ffff7855735 in malloc_consolidate () from /usr/lib/libc.so.6
#1 0x00007ffff7856a08 in _int_malloc () from /usr/lib/libc.so.6
#2 0x00007ffff7858cc0 in malloc () from /usr/lib/libc.so.6
#3 0x00007ffff7bb4b17 in ?? () from /usr/lib/libjpeg.so.8
#4 0x00007ffff7b9f225 in jpeg_stdio_dest () from /usr/lib/libjpeg.so.8
#5 0x0000000000400f2e in write_jpeg_file (
image_buffer=0x608070 "\002\002\002\002\002\002\366\366\366\365\365\365\001\001\001\003 \003\003\371\371\371\367\367\367\362\362\362\361\361\361\002\002\002\003\003\003\373\373\373\373\373\373\001\001\001\002\002\002", img_h=4, img_w=4, filename=0x7fffffffe6d1 "lol.jpg", quality=100) at jpegapi.c:39
#6 0x0000000000400e1f in main (argc=5, argv=0x7fffffffe2e8) at main.c:28
I have no idea where to search, any help is appreciated

The file opening can fail and yet you do a jpeg_stdio_dest call
bracket problem?
if ((outfile = fopen(filename, "wb+")) == NULL) {
fprintf(stderr, "can't open %s\n", filename);
exit(1);
}
else
{
printf("File successfully opened\n");
jpeg_stdio_dest(&cinfo, outfile);
}

Related

avcodec_find_decoder() - segmentation fault

This is my simple ffmpeg code.
I`m reading a .ogg from the file.
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
int main(int argc, char **argv){
av_register_all();
avcodec_register_all();
static const char *src_filename = NULL;
static AVFormatContext *input_format_context = NULL;
int ret; int error;
src_filename = argv[1];
//open audio file
if ((error = avformat_open_input(&input_format_context, src_filename, NULL, NULL)) < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");
return ret;
}else{
fprintf(stderr, "open file + \n");
}
and then call av_format_stream_info function.
// find stream info
error = avformat_find_stream_info(input_format_context, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");
}else{
fprintf(stderr, "find stream + \n");
}
everything is ok so far. but now when i call the avcodec_find_decoder function i get the segmentation fault.
for (int i=0; i < input_format_context->nb_streams; i++)
{
fprintf(stderr, "1.1\n");
AVStream *stream = input_format_context->streams[0];
fprintf(stderr, "1.2\n");
AVCodec *dec = avcodec_find_decoder(stream->codecpar->codec_id);
fprintf(stderr, "1.3\n");
}
return 0;
}
And this is my cmake:
cmake_minimum_required(VERSION 2.6)
project(decode_encode)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "-D__STDC_CONSTANT_MACROS")
find_path(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h)
find_library(AVCODEC_LIBRARY avcodec)
find_path(AVFORMAT_INCLUDE_DIR libavformat/avformat.h)
find_library(AVFORMAT_LIBRARY avformat)
find_path(AVUTIL_INCLUDE_DIR libavutil/avutil.h)
find_library(AVUTIL_LIBRARY avutil)
find_path(AVDEVICE_INCLUDE_DIR libavdevice/avdevice.h)
find_library(AVDEVICE_LIBRARY avdevice)
add_executable(readFewFrame readFewFrame.c)
target_include_directories(readFewFrame PRIVATE ${AVCODEC_INCLUDE_DIR} ${AVFORMAT_INCLUDE_DIR} ${AVUTIL_INCLUDE_DIR} ${AVDEVICE_INCLUDE_DIR})
target_link_libraries(readFewFrame PRIVATE ${AVCODEC_LIBRARY} ${AVFORMAT_LIBRARY} ${AVUTIL_LIBRARY} ${AVDEVICE_LIBRARY})
what exactly could be the cause of this error?

Passing data and retrieving data via same struct using threads

I need to read a file from a separate thread, to avoid hiccups in the flow of my opengl program. I already do that for loading textures and blending them using global variables, that works fine.
However now I need some separate threads to read small data files.
I have created a struct, which basically contains 2 args and 1 result.
It seems I can't do that or I got it wrong somewhere (or in many places)
Here is the sample code of my non proof of concept:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#define content_file "/home/tias/content.txt" //this file contains "foobar!!"
typedef struct {
int* reading; // 0 = not reading , 1 = reading , 2 = finished reading
char* content; // content of the file
char* file; // file to read
} struct_file_content;
struct_file_content first_file;
void *thread_read_file ( void* data ) {
struct_file_content *thisdata = (struct_file_content*) data;
long length;
int i = 0;
char readchar;
char * thiscontent = 0;
int reading_finished = 2;
int *ptr_to_reading_finished = (int*)malloc(sizeof(int));
ptr_to_reading_finished = &reading_finished;
fprintf(stdout,"thread_Read_file called with file: %s and reading: %u\n",(*thisdata).file,*(*thisdata).reading);
FILE * f = fopen ((*thisdata).file, "r");
if (f) {
fseek (f, 0, SEEK_END);
length = ftell (f);
fseek (f, 0, SEEK_SET);
if (length > 39) {
fprintf(stderr,"file %s is too big\n",(*thisdata).file);
exit (1);
}
thiscontent = (char*) malloc (length*sizeof(char));
if ( thiscontent ) {
fread (thiscontent, 1, length, f);
}
fclose (f);
thisdata->content = thiscontent;
} else {
fprintf (stderr, "cannot read file %s\n",(*thisdata).file);
exit (1);
}
sleep(1);
thisdata->reading = ptr_to_reading_finished;
fprintf(stdout,"finished reading: %u\n",*(*thisdata).reading);
fprintf(stdout,"content: %s\n",thiscontent);
pthread_exit(NULL);
return NULL;
}
main()
{
pthread_t thread1;
int filename_length = strlen(content_file);
int rfinish = 2;
int rbegin = 1;
first_file.reading = (int*) malloc(sizeof(int));
first_file.file = (char*) malloc((filename_length+1)*sizeof(char));
first_file.reading = &rbegin;
strcpy(first_file.file,content_file);
pthread_create( &thread1, NULL, thread_read_file, (void*) &first_file);
while ( *(first_file.reading) != 2 ) {
fprintf(stdout,"still reading, reading: %u\n",*(first_file.reading));
sleep(1);
}
fprintf(stdout,"exited control loop with file: %s, reading: %u, content: %s\n",first_file.file, *(first_file.reading), first_file.content);
}
Here's the result:
~/repository/thread/test$ ./tt
still reading, reading: 1
thread_Read_file called with file: /home/tias/content.txt and reading: 1
still reading, reading: 1
still reading, reading: 1
still reading, reading: 1
finished reading: 2
content: foobar!!
still reading, reading: 0
still reading, reading: 0
I was expecting reading = 2 to get out of the loop, instead it is 0.
Any idea on what I have to modify to make it work?
I have read about mutex and so, may be it is the way?
I had found my solution elegant and not working, your help is greatly appreciated.
typedef struct {
int* reading; // 0 = not reading , 1 = reading , 2 = finished reading
char* content; // content of the file
char* file; // file to read
} struct_file_content;
Why is reading a pointer type? It is used in the code as a flag, there is absolutely no need to make it a pointer, especially given that you dynamically allocate memory for this structure field. It complicates the design and is unnecessary. Go ahead and make that an int, not a pointer:
typedef struct {
int reading; // 0 = not reading , 1 = reading , 2 = finished reading
char *content; // content of the file
char *file; // file to read
} struct_file_content;
This simplifies the code in main() used to set up first_file:
first_file.reading = 1;
first_file.content = NULL;
first_file.file = content_file;
Note that there is no need to have first_file.file be dynamically allocated memory, since you know the file name (and size) at compile time. Keep things simple.
Next, you ignore a possible error return value from pthread_create(3). It returns non-zero in case of failure, and you should check for that. Something like this will do:
pthread_t thread1;
int thread_res = pthread_create(&thread1, NULL, thread_read_file, &first_file);
if (thread_res != 0) {
fprintf(stderr, "pthread_create(3) error: %s\n", strerror(thread_res));
exit(EXIT_FAILURE);
}
The code to wait for reading to finish is buggy and racy, you need to either synchronize access to the reading field of struct_file_content with a mutex, or properly wait for the thread to terminate before accessing the first_file again. Since the code does nothing but wait for the thread, pthread_join(3) is a much more reasonable choice here. You'd do something like:
int join_res = pthread_join(thread1, NULL);
if (join_res != 0) {
fprintf(stderr, "pthread_join(3) error: %s\n", strerror(join_res));
exit(EXIT_FAILURE);
}
Inside thread_read_file(), you probably want pthread_exit(3) when handling errors instead of exit(2), since the latter will terminate the entire process, not just the local thread. You also need to handle malloc(3) errors.
Here's the code with all of these issues addressed:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#define content_file "/home/tias/content.txt" //this file contains "foobar!!"
typedef struct {
int reading; // 0 = not reading , 1 = reading , 2 = finished reading
char *content; // content of the file
char *file; // file to read
} struct_file_content;
struct_file_content first_file;
void *thread_read_file(void *data) {
struct_file_content *thisdata = data;
long length;
char *thiscontent = NULL;
fprintf(stdout,"thread_Read_file called with file: %s and reading: %u\n", thisdata->file, thisdata->reading);
FILE *f = fopen (thisdata->file, "r");
if (f) {
fseek(f, 0, SEEK_END);
length = ftell(f);
fseek (f, 0, SEEK_SET);
if (length > 39) {
fprintf(stderr,"file %s is too big\n", thisdata->file);
pthread_exit(NULL);
}
thiscontent = malloc(length);
if (thiscontent) {
fread(thiscontent, 1, length, f);
} else {
perror("malloc(3) error");
pthread_exit(NULL);
}
fclose(f);
thisdata->content = thiscontent;
} else {
fprintf(stderr, "cannot open file %s\n", thisdata->file);
pthread_exit(NULL);
}
thisdata->reading = 2;
fprintf(stdout, "finished reading: %u\n", thisdata->reading);
fprintf(stdout, "content: %s\n", thiscontent);
return NULL;
}
int main(void) {
first_file.reading = 1;
first_file.content = NULL;
first_file.file = content_file;
pthread_t thread1;
int thread_res = pthread_create(&thread1, NULL, thread_read_file, &first_file);
if (thread_res != 0) {
fprintf(stderr, "pthread_create(3) error: %s\n", strerror(thread_res));
exit(EXIT_FAILURE);
}
int join_res = pthread_join(thread1, NULL);
if (join_res != 0) {
fprintf(stderr, "pthread_join(3) error: %s\n", strerror(join_res));
exit(EXIT_FAILURE);
}
fprintf(stdout, "Read file %s, reading: %u, content: %s\n", first_file.file, first_file.reading, first_file.content);
return 0;
}
UPDATE
From the comments, it seems like you want to do some additional processing and periodically test (at your convenience) whether the thread is done reading. Your approach of using a flag to test for termination is mostly correct, but you should synchronize access to the reading field of struct_file_content to make sure that you always get consistent values. As such, I suggest adding a mutex to struct_file_content that is used to control concurrent access to the reading field. You should lock the mutex every time you need to read or update reading.
So, the structure definition becomes:
typedef struct {
pthread_mutex_t read_mutex; // synchronize access to reading flag
int reading; // 0 = not reading , 1 = reading , 2 = finished reading
char *content; // content of the file
char *file; // file to read
} struct_file_content;
Then, as part of initializing struct_file_content, you need to remember to initialize the mutex. Here's how you'd do it in main():
int mutex_err = pthread_mutex_init(&first_file.read_mutex, NULL);
if (mutex_err != 0) {
fprintf(stderr, "pthread_mutex_init(3) error: %s\n", strerror(mutex_err));
exit(EXIT_FAILURE);
}
first_file.reading = 1;
first_file.content = NULL;
first_file.file = content_file;
Now, the loop in main() simply locks the mutex, checks the status of the reading field (breaking out if it is equal to 2), and unlocks the mutex. Something like:
int read_done = 0;
while (!read_done) {
mutex_err = pthread_mutex_lock(&first_file.read_mutex);
if (mutex_err != 0) {
fprintf(stderr, "pthread_mutex_lock(3) error: %s\n", strerror(mutex_err));
exit(EXIT_FAILURE);
}
/* Reading is finished when first_file.reading == 2 */
read_done = (first_file.reading == 2);
if (first_file.reading != 2)
printf("Still reading, reading: %u\n", first_file.reading);
mutex_err = pthread_mutex_unlock(&first_file.read_mutex);
if (mutex_err != 0) {
fprintf(stderr, "pthread_mutex_unlock(3) error: %s\n", strerror(mutex_err));
}
}
Of course, you also need to update the thread function to lock the mutex before modifying reading:
void *thread_read_file(void *data) {
struct_file_content *thisdata = data;
int mutex_res;
long length;
char *thiscontent = NULL;
mutex_res = pthread_mutex_lock(&thisdata->read_mutex);
if (mutex_res != 0) {
fprintf(stderr, "thread_read_file() failed to acquire mutex: %s\n", strerror(mutex_res));
pthread_exit(NULL);
}
fprintf(stdout, "thread_read_file() called with file: %s and reading: %u\n", thisdata->file, thisdata->reading);
mutex_res = pthread_mutex_unlock(&thisdata->read_mutex);
if (mutex_res != 0) {
fprintf(stderr, "thread_read_file() failed to release mutex: %s\n", strerror(mutex_res));
pthread_exit(NULL);
}
FILE *f = fopen(thisdata->file, "r");
if (f) {
fseek(f, 0, SEEK_END);
length = ftell(f);
fseek (f, 0, SEEK_SET);
if (length > 39) {
fprintf(stderr, "file %s is too big\n", thisdata->file);
pthread_exit(NULL);
}
thiscontent = malloc(length);
if (thiscontent) {
fread(thiscontent, 1, length, f);
} else {
perror("malloc(3) error");
pthread_exit(NULL);
}
fclose(f);
thisdata->content = thiscontent;
} else {
fprintf(stderr, "cannot open file %s\n", thisdata->file);
pthread_exit(NULL);
}
mutex_res = pthread_mutex_lock(&thisdata->read_mutex);
if (mutex_res != 0) {
fprintf(stderr, "thread_read_file() failed to acquire mutex: %s\n", strerror(mutex_res));
pthread_exit(NULL);
}
thisdata->reading = 2;
fprintf(stdout, "finished reading: %u\n", thisdata->reading);
mutex_res = pthread_mutex_unlock(&thisdata->read_mutex);
if (mutex_res != 0) {
fprintf(stderr, "thread_read_file() failed to release mutex: %s\n", strerror(mutex_res));
pthread_exit(NULL);
}
fprintf(stdout, "content: %s\n", thiscontent);
return NULL;
}
That should be enough. Here's the full code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#define content_file "/home/tias/content.txt" //this file contains "foobar!!"
typedef struct {
pthread_mutex_t read_mutex; // synchronize access to reading flag
int reading; // 0 = not reading , 1 = reading , 2 = finished reading
char *content; // content of the file
char *file; // file to read
} struct_file_content;
struct_file_content first_file;
void *thread_read_file(void *data) {
struct_file_content *thisdata = data;
int mutex_res;
long length;
char *thiscontent = NULL;
mutex_res = pthread_mutex_lock(&thisdata->read_mutex);
if (mutex_res != 0) {
fprintf(stderr, "thread_read_file() failed to acquire mutex: %s\n", strerror(mutex_res));
pthread_exit(NULL);
}
fprintf(stdout, "thread_read_file() called with file: %s and reading: %u\n", thisdata->file, thisdata->reading);
mutex_res = pthread_mutex_unlock(&thisdata->read_mutex);
if (mutex_res != 0) {
fprintf(stderr, "thread_read_file() failed to release mutex: %s\n", strerror(mutex_res));
pthread_exit(NULL);
}
FILE *f = fopen(thisdata->file, "r");
if (f) {
fseek(f, 0, SEEK_END);
length = ftell(f);
fseek (f, 0, SEEK_SET);
if (length > 39) {
fprintf(stderr, "file %s is too big\n", thisdata->file);
pthread_exit(NULL);
}
thiscontent = malloc(length);
if (thiscontent) {
fread(thiscontent, 1, length, f);
} else {
perror("malloc(3) error");
pthread_exit(NULL);
}
fclose(f);
thisdata->content = thiscontent;
} else {
fprintf(stderr, "cannot open file %s\n", thisdata->file);
pthread_exit(NULL);
}
mutex_res = pthread_mutex_lock(&thisdata->read_mutex);
if (mutex_res != 0) {
fprintf(stderr, "thread_read_file() failed to acquire mutex: %s\n", strerror(mutex_res));
pthread_exit(NULL);
}
thisdata->reading = 2;
fprintf(stdout, "finished reading: %u\n", thisdata->reading);
mutex_res = pthread_mutex_unlock(&thisdata->read_mutex);
if (mutex_res != 0) {
fprintf(stderr, "thread_read_file() failed to release mutex: %s\n", strerror(mutex_res));
pthread_exit(NULL);
}
fprintf(stdout, "content: %s\n", thiscontent);
return NULL;
}
int main(void) {
int mutex_err = pthread_mutex_init(&first_file.read_mutex, NULL);
if (mutex_err != 0) {
fprintf(stderr, "pthread_mutex_init(3) error: %s\n", strerror(mutex_err));
exit(EXIT_FAILURE);
}
first_file.reading = 1;
first_file.content = NULL;
first_file.file = content_file;
pthread_t thread1;
int thread_res = pthread_create(&thread1, NULL, thread_read_file, &first_file);
if (thread_res != 0) {
fprintf(stderr, "pthread_create(3) error: %s\n", strerror(thread_res));
exit(EXIT_FAILURE);
}
int read_done = 0;
while (!read_done) {
mutex_err = pthread_mutex_lock(&first_file.read_mutex);
if (mutex_err != 0) {
fprintf(stderr, "pthread_mutex_lock(3) error: %s\n", strerror(mutex_err));
exit(EXIT_FAILURE);
}
/* Reading is finished when first_file.reading == 2 */
read_done = (first_file.reading == 2);
if (first_file.reading != 2)
printf("Still reading, reading: %u\n", first_file.reading);
mutex_err = pthread_mutex_unlock(&first_file.read_mutex);
if (mutex_err != 0) {
fprintf(stderr, "pthread_mutex_unlock(3) error: %s\n", strerror(mutex_err));
}
}
/* Here we don't need to lock because the thread has finished and no other thread is
* using this struct
*/
fprintf(stdout, "Read file %s, reading: %u, content: %s\n", first_file.file, first_file.reading, first_file.content);
free(first_file.content);
mutex_err = pthread_mutex_destroy(&first_file.read_mutex);
if (mutex_err != 0) {
fprintf(stderr, "Warning: Error destroying mutex: %s\n", strerror(mutex_err));
}
return 0;
}
Note that I added cleanup code in the end of main(). Even though it is not necessary (because the program is about to terminate), it is there to make sure you don't forget what kind of cleanup needs to be done once a thread terminates.

Error when decode AAC with avcodec_decode_audio4()

I'm trying to decode AAC with FFmpeg native decoder and encountered an error
SSR is not implemeted. Update your FFmpeg version to newest from Git. If the problem still occurs, it mean that your file has a feature which has not implemented.
Function avcodec_decode_audio4() return -1163346256. Is this because of FFmpeg version? I downloaded shared and dev version from here. Is this up to date?
Here is the source code:
#include "stdafx.h"
#include "stdio.h"
#include "conio.h"
extern "C"
{
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif
#include <libavcodec\avcodec.h>
#include <libavformat/avformat.h>
}
// compatibility with newer API
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1)
#define av_frame_alloc avcodec_alloc_frame
#define av_frame_free avcodec_free_frame
#endif
#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096
static void audio_decode_example(const char *outfilename, const char *filename);
int main(int argc, char *argv[]) {
audio_decode_example("D:\\sample.pcm","D:\\sample.m4a");
getch();
return 0;
}
/*
* Audio decoding.
*/
static void audio_decode_example(const char *outfilename, const char *filename)
{
AVCodec *codec;
AVFormatContext *pFormatCtx = NULL;
AVCodecContext *pCodecCtxOrig = NULL;
AVCodecContext * pCodecCtx= NULL;
int len;
FILE *f, *outfile;
uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
AVPacket avpkt;
AVFrame *decoded_frame = NULL;
av_register_all();
av_init_packet(&avpkt);
printf("Decode audio file %s to %s\n", filename, outfilename);
// Open file to get format context
if(avformat_open_input(&pFormatCtx, filename, NULL, NULL)!=0){
printf("Couldn't open file");
return; // Couldn't open file
}
// Retrieve stream information
if(avformat_find_stream_info(pFormatCtx, NULL)<0){
printf("Couldn't find stream information");
return; // Couldn't find stream information
}
// Dump information about file onto standard error
av_dump_format(pFormatCtx, 0, filename, 0);
// Find the first audio stream
int audioStream = -1;
int i =0;
for(i=0; i<pFormatCtx->nb_streams; i++) {
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO) {
audioStream=i;
break;
}
}
if(audioStream==-1) {
printf("Didn't find a audio stream");
return; // Didn't find a audio stream
}
// Get a pointer to the codec context for the audio stream
pCodecCtxOrig=pFormatCtx->streams[audioStream]->codec;
// Find the decoder for the audio stream
codec=avcodec_find_decoder(pCodecCtxOrig->codec_id);
if(codec==NULL) {
fprintf(stderr, "Codec not found\n");
return; // Codec not found
}
pCodecCtx = avcodec_alloc_context3(codec);
if (!pCodecCtx) {
fprintf(stderr, "Could not allocate audio codec context\n");
return;
}
if(avcodec_copy_context(pCodecCtx, pCodecCtxOrig) != 0) {
fprintf(stderr, "Couldn't copy codec context");
return; // Error copying codec context
}
/* open it */
if (avcodec_open2(pCodecCtx, codec, NULL) < 0) {
fprintf(stderr, "Could not open codec\n");
return;
}
f = fopen(filename, "rb");
if (!f) {
fprintf(stderr, "Could not open %s\n", filename);
return;
}
outfile = fopen(outfilename, "wb");
if (!outfile) {
av_free(pCodecCtx);
return;
}
/* decode until eof */
avpkt.data = inbuf;
avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
while (avpkt.size > 0) {
int i, ch;
int got_frame = 0;
if (!decoded_frame) {
if (!(decoded_frame = av_frame_alloc())) {
fprintf(stderr, "Could not allocate audio frame\n");
return;
}
}
len = avcodec_decode_audio4(pCodecCtx, decoded_frame, &got_frame, &avpkt);
if (len < 0) {
fprintf(stderr, "Error while decoding. len = %d \n",len);
return;
}
if (got_frame) {
/* if a frame has been decoded, output it */
int data_size = av_get_bytes_per_sample(pCodecCtx->sample_fmt);
if (data_size < 0) {
/* This should not occur, checking just for paranoia */
fprintf(stderr, "Failed to calculate data size\n");
return;
}
for (i=0; i < decoded_frame->nb_samples; i++)
for (ch=0; ch < pCodecCtx->channels; ch++)
fwrite(decoded_frame->data[ch] + data_size*i, 1, data_size, outfile);
}
avpkt.size -= len;
avpkt.data += len;
avpkt.dts =
avpkt.pts = AV_NOPTS_VALUE;
if (avpkt.size < AUDIO_REFILL_THRESH) {
/* Refill the input buffer, to avoid trying to decode
* incomplete frames. Instead of this, one could also use
* a parser, or use a proper container format through
* libavformat. */
memmove(inbuf, avpkt.data, avpkt.size);
avpkt.data = inbuf;
len = fread(avpkt.data + avpkt.size, 1,
AUDIO_INBUF_SIZE - avpkt.size, f);
if (len > 0)
avpkt.size += len;
}
}
fclose(outfile);
fclose(f);
avcodec_close(pCodecCtx);
av_free(pCodecCtx);
av_frame_free(&decoded_frame);
}
I have also read this question: How to decode AAC using avcodec_decode_audio4? but no solution is provided.
f = fopen(filename, "rb");
if (!f) {
fprintf(stderr, "Could not open %s\n", filename);
return;
}
outfile = fopen(outfilename, "wb");
if (!outfile) {
av_free(pCodecCtx);
return;
}
/* decode until eof */
avpkt.data = inbuf;
avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
while (avpkt.size > 0) {
int i, ch;
int got_frame = 0;
Yeah, that's not going to work. You can't dump raw bytes from some random muxing format (potentially mp4) into a decoder and expect it to work. Use av_read_frame() to read individual audio packets from the muxing format, and feed the resulting AVPacket into the decoder using avcodec_decode_audio4(). See e.g. the dranger api tutorial. I know api-example.c uses the above code, but that unfortunately only works for a very limited subset of cases. Also see the detailed description in the API docs.

Sqlite3_bind_text segmentation fault

My app does a recursive scan of a given directory, I store each unique path in a database.
At one point I get a segfault and glibc fires:
*** glibc detected *** ./test: double free or corruption (!prev): 0x08cd1a20 ***
gdb confirms it.
The problem occurs when calling the function below:
int
populatePathDB(sqlite3* db, char *absolutePath)
{
char *sql;
sqlite3_stmt *stmt ;
int ret;
sql = "INSERT INTO paths (path) VALUES (?)";
ret = sqlite3_prepare_v2(db,sql,-1,&stmt,NULL);
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db));
ret = sqlite3_bind_text(stmt, 1, absolutePath, -1, SQLITE_STATIC);
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db));
sqlite3_step(stmt);
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db));
/* sqlite3_clear_bindings(stmt);
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db));
sqlite3_reset(stmt);
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db)); */
ret = sqlite3_finalize( stmt );
if ( ret != SQLITE_OK)
DB_ERR(db, sqlite3_errmsg(db));
return SQLITE_OK;
}
I guess the variable absolutePath (allocated by the caller) is deleted twice. Even Using SQLITE_TRANSIENT i've got the same fault.
Any ideas?
Adding recursive scan function:
int walkDir( char *dir, unsigned int recursive)
{
DIR* dirstream;
struct stat statbuf;
struct dirent *entry = NULL;
int exists, fd;
size_t dlen, entlen, nlen;
size_t buflen = 0;
char *baseName = NULL;
extern sqlite3 *magicDB_g;
extern sqlite3 *pathDB_g;
assert (dir !=NULL);
if ( ( dirstream = opendir(dir) ) == NULL ) {
ERR_MSG("opendir");
return (EXIT_FAILURE);
}
dlen = strlen(dir);
buflen = MEMCHUNK;
if (dlen >= buflen)
buflen = roundToNextPowerOf2(dlen);
baseName = xmalloc(buflen);
while ( ( entry = readdir(dirstream) ) ) {
if(!strcmp(".",entry->d_name) ||
! strcmp("..",entry->d_name))
continue;
if (entry->d_name[0] == '.')
continue;
nlen = dlen + (entlen = strlen(entry->d_name));
if (unlikely(nlen + 2 > buflen) )
xrealloc(baseName, buflen << 1);
if (dlen == 1 && *dir == '/' )
sprintf(baseName, "%s%s" , dir, entry->d_name);
else
sprintf(baseName, "%s/%s" , dir, entry->d_name);
/*snprintf (baseName, need + 2,"%s/%s", baseName, entry->d_name);*/
exists = lstat(baseName, &statbuf);
if (exists < 0)
continue;
if ( S_ISREG(statbuf.st_mode) && statbuf.st_size != 0 )
{
if ((fd = open(baseName, O_RDONLY)) == -1) {
ERR_MSG("open");
continue;
}
//fileSignature_v1(fd,NBYTES,magicDB_g);
if ( close(fd) == -1)
ERR_MSG("close");
}
if ( S_ISDIR(statbuf.st_mode) )
{
/* Create a absolute path database with unique entries */
populatePathDB(pathDB_g, baseName); <-- No segfault if not called.
if (recursive) {
printf("basename: %s\n",baseName);
walkDir(baseName,recursive);
}
}
}
free(baseName); <-- Seems to be deleted twice when back from populatePathDB()
if (closedir(dirstream) == -1)
ERR_MSG("closedir");
return (EXIT_SUCCESS);
}
Here's the error statement:
Program received signal SIGSEGV, Segmentation fault.
_int_malloc (av=0x379440, bytes=34) at malloc.c:3598
3598 malloc.c: Aucun fichier ou dossier de ce type.
(gdb) bt
#0 _int_malloc (av=0x379440, bytes=34) at malloc.c:3598
#1 0x0024fd3c in __GI___libc_malloc (bytes=34) at malloc.c:2924
#2 0x0011541f in local_strdup (s=0xb7fe2a8c "/lib/i386-linux-gnu/libgcc_s.so.1") at dl-load.c:162
#3 0x001185d4 in _dl_map_object (loader=<optimized out>, name=<optimized out>, type=2, trace_mode=0, mode=-1879048191, nsid=0) at dl-load.c:2473
#4 0x00122d5d in dl_open_worker (a=0xbfffe690) at dl-open.c:225
#5 0x0011ecbf in _dl_catch_error (objname=0xbfffe6b4, errstring=0xbfffe6b8, mallocedp=0xbfffe6bf, operate=0x122c30 <dl_open_worker>, args=0xbfffe690)
at dl-error.c:178
#6 0x001227e4 in _dl_open (file=0x334345 "libgcc_s.so.1", mode=-2147483647, caller_dlopen=0x2d7e38, nsid=-2, argc=2, argv=0xbffff314, env=0x8051040)
at dl-open.c:639
#7 0x002fbd41 in do_dlopen (ptr=0xbfffe840) at dl-libc.c:89
#8 0x0011ecbf in _dl_catch_error (objname=0xbfffe814, errstring=0xbfffe818, mallocedp=0xbfffe81f, operate=0x2fbce0 <do_dlopen>, args=0xbfffe840)
at dl-error.c:178
#9 0x002fbe37 in dlerror_run (operate=<optimized out>, args=<optimized out>) at dl-libc.c:48
#10 0x002fbec7 in __GI___libc_dlopen_mode (name=0x334345 "libgcc_s.so.1", mode=-2147483647) at dl-libc.c:165
#11 0x002d7e38 in init () at ../sysdeps/i386/backtrace.c:44
#12 0x00388e8e in pthread_once () at ../nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S:122
#13 0x002d80a5 in __GI___backtrace (array=0xbfffee90, size=64) at ../sysdeps/i386/backtrace.c:121
#14 0x00241310 in __libc_message (do_abort=2, fmt=0x3393bc "*** glibc detected *** %s: %s: 0x%s ***\n") at ../sysdeps/unix/sysv/linux/libc_fatal.c:180
#15 0x0024be42 in malloc_printerr (action=<optimized out>, str=<optimized out>, ptr=0x80c4eb8) at malloc.c:5007
#16 0x0804aa8f in walkDir (dir=0x8075a60 "/home/olivier/Téléchargements", recursive=1) at dirtraverser.c:251
#17 0x0804aa63 in walkDir (dir=0x80528f8 "/home/olivier", recursive=1) at dirtraverser.c:245
#18 0x0804bdc0 in main (argc=2, argv=0xbffff314) at main.c:246
Your xrealloc call (xrealloc(baseName, buflen << 1);) is wrong: you aren't assigning its result to baseName. xrealloc may free the buffer you give it (and return a different pointer), so if you don't assign the result then you may double-free the buffer.

Read the content of a file to memory, result different from 32bit os and 64bit os

I wrote a function below to read the content of a file to memory.
It works well on my local machine(Ubuntu 32bit), but it produces wrong result on server(CentOS 64bit).
Wrong case:
With a 40 byte file, the content is below, on the 64bit os, it gave me wrong result.
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
The code:
char* file_get_contents(const char *filename) {
FILE *stream = NULL;
char *content = NULL;
size_t ret;
struct stat st;
if ((stream = fopen(filename,"r")) == NULL) {
fprintf(stderr, "Failed to open file %s\n", filename);
exit(1002);
}
if(stat(filename, &st) < 0) {
fprintf(stderr, "Failed to stat file %s\n", filename);
exit(1002);
}
content = malloc(st.st_size);
ret = fread(content, 1, st.st_size, stream);
if (ret != st.st_size) {
fprintf(stderr, "Failed to read file %s\n", filename);
exit(1002);
}
fclose(stream);
return content;
}
Your file_get_contents cannot be correctly used by its caller. It returns a char * but not its lenght, nor does it return a string (i.e. it isn't null terminated.).
As long as you're reading text, do e.g.
content = malloc(st.st_size + 1); // + 1 here for the nul terminator
ret = fread(content, 1, st.st_size, stream);
if (ret != st.st_size) {
fprintf(stderr, "Failed to read file %s\n", filename);
exit(1002);
}
content[st.st_size] = 0; //nul terminate

Resources