Writing improper number of frames using PortAudio? - c

Running my program, I appear to not be writing the correct amount of frames according to the index.
$ ./test
Now recording!! Please speak into the microphone.
index = 0
Writing to: test.flac
audio.h:
#include <stdint.h>
#include <string.h>
typedef struct
{
uint32_t duration;
uint16_t format_type;
uint16_t number_of_channels;
uint32_t sample_rate;
uint32_t frameIndex; /* Index into sample array. */
uint32_t maxFrameIndex;
char* recordedSamples;
} AudioData;
int recordFLAC(AudioData* data, const char *fileName);
AudioData* initAudioData(uint32_t sample_rate, uint16_t channels, uint32_t duration);
capture.c:
#include <stdio.h>
#include <stdlib.h>
#include <portaudio.h>
#include <sndfile.h>
#include "audio.h"
AudioData* initAudioData(uint32_t sample_rate, uint16_t channels, uint32_t duration)
{
AudioData* data = malloc(sizeof(*data));
if (!data) return NULL;
data->duration = duration;
data->format_type = 1;
data->number_of_channels = channels;
data->sample_rate = sample_rate;
data->frameIndex = 0;
data->maxFrameIndex = sample_rate * duration;
data->recordedSamples = malloc(sizeof(data->maxFrameIndex));
if(!data->maxFrameIndex) return NULL;
return data;
}
static int recordCallback(const void *inputBuffer, void *outputBuffer, unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
{
AudioData* data = (AudioData*)userData;
const char* buffer_ptr = (const char*)inputBuffer;
char* index_ptr = &data->recordedSamples[data->frameIndex];
(void) outputBuffer;
(void) timeInfo;
(void) statusFlags;
long framesToCalc;
long i;
int finished;
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
if(framesLeft < frameCount){
framesToCalc = framesLeft;
finished = paComplete;
}else{
framesToCalc = frameCount;
finished = paContinue;
}
if(!inputBuffer){
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = 0;
}
}else{
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = *buffer_ptr++;
}
}
data->frameIndex += framesToCalc;
return finished;
}
int recordFLAC(AudioData* data, const char *fileName)
{
PaStreamParameters inputParameters;
PaStream* stream;
int err = 0;
int totalFrames = data->maxFrameIndex;
int numSamples;
int numBytes;
char max, val;
double average;
numSamples = totalFrames * data->number_of_channels;
numBytes = numSamples;
data->recordedSamples = malloc(numBytes);
if(!data->recordedSamples)
{
printf("Could not allocate record array.\n");
goto done;
}
for(int i = 0; i < numSamples; i++) data->recordedSamples[i] = 0;
if((err = Pa_Initialize())) goto done;
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto done;
}
inputParameters.channelCount = data->number_of_channels; /* stereo input */
inputParameters.sampleFormat = data->format_type;
inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
/* Record some audio. -------------------------------------------- */
err = Pa_OpenStream(&stream, &inputParameters, NULL, data->sample_rate, paFramesPerBufferUnspecified, paClipOff, recordCallback, &data);
if(err) goto done;
if((err = Pa_StartStream(stream))) goto done;
puts("Now recording!! Please speak into the microphone.");
while((err = Pa_IsStreamActive(stream)) == 1)
{
Pa_Sleep(1000);
printf("index = %d\n", data->frameIndex);
}
if( err < 0 ) goto done;
err = Pa_CloseStream(stream);
if(err) goto done;
/* Measure maximum peak amplitude. */
max = 0;
average = 0.0;
for(int i = 0; i < numSamples; i++)
{
val = data->recordedSamples[i];
val = abs(val);
if( val > max )
{
max = val;
}
average += val;
}
average /= (double)numSamples;
done:
Pa_Terminate();
if(err)
{
fprintf(stderr, "An error occured while using the portaudio stream\n");
fprintf(stderr, "Error number: %d\n", err);
fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err));
err = 1; /* Always return 0 or 1, but no other return codes. */
}
else
{
SF_INFO sfinfo;
sfinfo.channels = 1;
sfinfo.samplerate = data->sample_rate;
sfinfo.format = SF_FORMAT_FLAC | SF_FORMAT_PCM_16;
// open to file
printf("Writing to: %s\n", fileName);
SNDFILE * outfile = sf_open(fileName, SFM_WRITE, &sfinfo);
if (!outfile) return -1;
// prepare a 3 second long buffer (sine wave)
const int size = data->sample_rate * 3;
// write the entire buffer to the file
sf_write_raw(outfile, data->recordedSamples, size);
// force write to disk
sf_write_sync(outfile);
// don't forget to close the file
sf_close(outfile);
}
return err;
}
I'm not quite sure where I am going wrong, I know I need to be writing more frames. Any suggestions?

There seems to be something wrong with your assumptions about the sample format. In the callback you are using char * (single bytes) for the sample format, but in your libsndfile call you're opening a 16 bit file with SF_FORMAT_PCM_16.
This is not so good:
data->format_type = 1;
I recommend using one of the symbolic constants in the PortAudio library for sample formatting. Maybe you want a 16 bit one? And if so, you want to be using short* not char* in the PA callback.
Finally, if your channel count is not 1, the copy loops are incorrect:
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = 0;
}
A "frame" contains data for all channels, so for example, if it's a stereo input your iteration needs to deal with both left and right channels like this:
for(i = 0; i < framesToCalc; i++){
*index_ptr++ = 0; // left
*index_ptr++ = 0; // right
}
Same for the other loops.

Related

How to Combine 2 Struct arrays in C

iv tried a lot of solutions to try to get this working (i.e using memcpy etc) I cant seem to find the issue, depending on what I try I either end up with gibberish or SEGV
iv spent a lot of time already googling and trying different ways, i still cant figure out why the arrays won't combine successfully
#include <stdio.h>
#include <stdint.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/syscall.h>
#include <unistd.h>
#define log_info printf
typedef struct
{
char* name;
//size_t size;
} entry_t;
/* qsort struct comparison function (C-string field) */
static int struct_cmp_by_name(const void* a, const void* b)
{
entry_t* ia = (entry_t*)a;
entry_t* ib = (entry_t*)b;
return strcmp(ia->name, ib->name);
/* strcmp functions works exactly as expected from comparison function */
}
entry_t* get_item_entries(const char* dirpath, int* count)
{
struct dirent* dent;
char buffer[512]; // fixed buffer
int dfd = 0,
n, r = 1; // item counter, rounds to loop
entry_t* p = NULL; // we fill this struct with items
loop:
n = 0;
printf("loop: %d, count:%d\n", r, *count);
// try to open dir
dfd = open(dirpath, O_RDONLY, 0);
if (dfd < 0)
{
printf("Invalid directory. (%s)\n", dirpath);
*count = -1;
return NULL;
}
else
{
printf("open(%s)\n", dirpath);
}
memset(buffer, 0, sizeof(buffer));
while (syscall(SYS_getdents, dfd, buffer, sizeof(buffer)) != 0)
{
dent = (struct dirent*)buffer;
while (dent->d_fileno)
{ // skip `.` and `..`
if (!strncmp(dent->d_name, "..", 2)
|| !strncmp(dent->d_name, ".", 1)) goto skip_dent;
// deal with filtering outside of this function, we just skip .., .
switch (r)
{ // first round: just count items
case 1:
{
// skip special cases
if (dent->d_fileno == 0) goto skip_dent;
break;
}
// second round: store filenames
case 0: p[n].name = strdup(dent->d_name); break;
}
n++;
skip_dent:
dent = (struct dirent*)((void*)dent + dent->d_reclen);
if (dent == (void*)&buffer[512]) break; // refill buffer
}
memset(buffer, 0, sizeof(buffer));
}
close(dfd);
// on first round, calloc for our list
if (!p)
{ // now n holds total item count, note it
p = calloc(n, sizeof(entry_t));
*count = n;
}
// first round passed, loop
r--; if (!r) goto loop;
// report count
printf("%d items at %p, from 1-%d\n", *count, (void*)p, *count);
/* resort using custom comparision function */
qsort(p, *count, sizeof(entry_t), struct_cmp_by_name);
// report items
//for (int i = 0; i < num; ++i) log_error( "%s", p[i].name);
return p;
}
int main(int argc, char* argv[])
{
int HDD_count = -1;
uint32_t total = -1;
int ext_count = -1;
entry_t* e = NULL;
entry_t *HDD = get_item_entries("/mnt/f/n", &HDD_count);
entry_t* ext = get_item_entries("/mnt/f/dls", &ext_count);
total = ext_count + HDD_count;
e = (entry_t*)malloc(sizeof *e * total);
if (e != NULL)
{
for (int i = 1; i < HDD_count; i++)
{
log_info("HDD[%i].name %s\n", i, HDD[i].name);
e[i].name = strdup(HDD[i].name);
}
for (int i = 1; i < ext_count; i++)
{
log_info("ext[%i].name %s\n", i, ext[i].name);
e[i + HDD_count].name = strdup(ext[i].name);
}
}
else
printf("Failed to Allocate the Array");
char tmp[256];
int i = 1, j;
for(j = 1; j <= total; j++)
{
snprintf(&tmp[0], 255, "%s", e[ j].name);
log_info("%i:%s\n", j , tmp);
}
return 0;
}
Here is a rewrite of a snippet of main() that I mentioned in my comment above:
#define CHECK(p, msg) if(!(p)) { printf("%s:%d: %s", __FILE__, __LINE__, msg); return 1;}
...
entry_t *HDD = get_item_entries("/mnt/f/n", &HDD_count);
CHECK(HDD, "HDD failed to get entries");
entry_t *ext = get_item_entries("/mnt/f/dls", &ext_count);
CHECK(ext, "ext failed to get entries");
uint32_t total = HDD_count + ext_count;
entry_t *e = malloc(total * sizeof(*e));
CHECK(e, "malloc failed");
for(int i = 0; i < HDD_count; i++) {
log_info("HDD[%i].name %s\n", i, HDD[i].name);
e[i].name = strdup(HDD[i].name);
}
// write a function instead of duplicating code?
for (int i = 0; i < ext_count; i++) {
log_info("ext[%i].name %s\n", i, ext[i].name);
e[HDD_count + i].name = strdup(ext[i].name);
}
It looks like a short lived program, but I would still free the values from strdup() and e itself.

Modifying extension list in X509 certificate using OpenSSL in C

I am tring to insert signed sct into a precertificate that has a poison extension.
So I first remove the poison extension, then add the SCT.
This is what I've done:
int main(int argc, char **argv) {
size_t lenCert = 0, lenCert2 = 0;
char *filePEM = "testpem/precert3.cert.pem";
char *strCertPem = loadFileContent(filePEM, &lenCert);
const X509 *cert = parse_certificate(strCertPem);
X509 *certRef = X509_dup(cert);
if(!cert || cert==NULL){
printf("Failed parsing\n");
return -1;
}
int len_init = -1;
unsigned char *buf_init = NULL;
len_init = i2d_X509(certRef, &buf_init);
if(len_init < 0){
printf("INIT: failed conversion to DER\n");
return -1;
} else {
printf("INIT: Successful conversion to DER[%d]\n", len_init);
}
printf("size certificate: %ld\n", lenCert);
X509_EXTENSION *tmpext;
const STACK_OF(X509_EXTENSION) *allExt = X509_get0_extensions(cert);
const STACK_OF(X509_EXTENSION) *allExt2 = X509_get0_extensions(certRef);
int my_idx = X509v3_get_ext_by_NID(allExt, NID_ct_precert_poison, -1);
int idx = my_idx;
int cc = X509_get_ext_count(cert);
printf("Extension count in cert BEFORE = %d\n", cc);
printf((allExt==NULL) ? "Extensions extraction FAILED\n" : "Extensions extraction SUCCESS\n");
int counter = X509v3_get_ext_count(allExt);
printf("Extension[%d] count BEFORE = %d\n", idx, counter);
do {
tmpext = X509v3_get_ext(allExt, idx);
X509v3_delete_ext(allExt, idx);
X509_EXTENSION_free(tmpext);
idx = X509v3_get_ext_by_NID(allExt, NID_ct_precert_poison, -1);
printf("pass\n");
} while (idx != -1);
counter = X509v3_get_ext_count(allExt);
printf("Extension count AFTER = %d\n", counter);
if(X509_cmp( cert, certRef)){
printf("Certificate modified\n\n");
} else {
printf("FAILED!!! \n");
}
cc = X509_get_ext_count(cert);
printf("Extension count in cert AFTER = %d\n", cc);
int len_inter;
unsigned char *buf_inter = NULL;
len_inter = i2d_X509(cert, &buf_inter);
if(len_inter < 0){
printf("INTERMEDIATE: failed conversion to DER\n");
return -1;
} else {
printf("INTERMEDIATE: Successful conversion to DER[%d]\n", len_inter);
}
unsigned char *dersct;
size_t lenSCTList = 0;
char *b64SCTList = "BIF6AHgAdgCwzIPlpfl9a698CcwoSQSHKsfoixMsY1C3xv0m4WxsdwAAAWZ7z/DQAAAEAwBHMEUCIQDKJPPQhWqje1rQq+T06x0iNlLT7rX71k23VPZkhm/QCwIgfhwNK7izeq0fHAlu7HuYRjmvym51RRdlNWhd50LQdu4=";
int b64Res = Base64Decode(b64SCTList, &dersct, &lenSCTList); //Decodes a base64 encoded string
printf("size final SCT List: %ld\n", lenSCTList);
STACK_OF(SCT) * scts = d2i_SCT_LIST(NULL, (const unsigned char **) &dersct, lenSCTList);
if(scts==NULL){
printf("Could not convert SCT List!");
return -1;
}
printf("SCT List converted !\n");
ASN1_OCTET_STRING *val = ASN1_OCTET_STRING_new();
ASN1_OCTET_STRING_set(val, dersct, (int)lenSCTList);
X509_EXTENSION* extSCT = X509_EXTENSION_create_by_NID(NULL, NID_ct_precert_scts, 0, val);
if(extSCT){
printf("created extension\n");
} else {
printf("Failed to create extension\n");
return -1;
}
if( X509_add_ext(cert, extSCT, -1)) {
printf("Extension added\n");
// X509_EXTENSION_free(extSCT);
} else {
printf("failed to add extension\n");
return -1;
}
int len_final;
unsigned char *buf_final = NULL;
len_final = i2d_X509(cert, &buf_final);
if(len_final < 0){
printf("FINAL: failed conversion to DER\n");
return -1;
} else {
printf("FINAL: Successful conversion to DER[%d]\n", len_final);
}
BIO *Cout = BIO_new(BIO_s_mem());
PEM_write_bio_X509(Cout, cert);
char* data;
const long len = BIO_get_mem_data(Cout, &data);
cc = X509_get_ext_count(cert);
printf("Extension count in cert AFTER = %d\n", cc);
printf("\ndata[%ld]: \n%s\n\n", len, data);
BIO_free_all(Cout);
int my_idx2 = X509_get_ext_by_NID(cert, NID_ct_precert_poison, -1);
X509_EXTENSION* extPoison2 = X509_get_ext(cert, my_idx2);
if(!extPoison2){
printf("failed last extension[%d] extract \n ", my_idx2);
return -1;
} else {
printf("Succeeded last extension extract[%d]\n ", my_idx2);
}
return 0;
}
This code seems to work, all step are fine, problem is, the final certificate displayed, when I save it to a file and run the command:
openssl x509 -in cert.pem -noout -text
it is the same as the original precertificate, it contains the poison extension and no SCT.
Even comparing both files, they are identical.
Where did I go wrong?
Your main problem is that for X509 X509_CRL X509_REQ when created by parsing input i.e. not built up from scratch OpenSSL saves the tbs encoding and reuses it on output (and digesting and comparison, which is why your X509_cmp failed) even if you have changed some of the fields that go in that encoding, unless you sign the change(s) which you must to make the resulting object valid anyway. In short, you need to call X509_sign() or the extended form X509_sign_ctx() after making your changes.
After fixing that you have another problem: it does remove the poison ext and add an SCT ext -- which contains garbage, because your unnecessary call to d2i_SCT_LIST has changed the pointer you use. Removing that, plus your other unneeded cruft, produces the following code that works (with a precert and key of my own) to produce a correct-looking cert, though of course the SCTs you provided aren't valid for it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/ct.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
int main(int argc, char **argv) {
// size_t lenCert = 0, lenCert2 = 0;
// char *filePEM = "testpem/precert3.cert.pem";
// replace mystery routines by one PEM:
FILE *infile = fopen(argv[1],"r"); if(!infile) exit(1);
X509 *cert = PEM_read_X509 (infile, NULL, NULL, NULL);
fclose(infile);
X509 *certRef = X509_dup(cert);
if(!cert || cert==NULL){ // redundant, and too late
printf("Failed parsing\n");
return -1;
}
#if 0 // useless
unsigned char *buf_init = NULL;
int len_init = i2d_X509(certRef, &buf_init);
#endif
//--printf("size certificate: %ld\n", lenCert);
//--X509_EXTENSION *tmpext;
const STACK_OF(X509_EXTENSION) *allExt = X509_get0_extensions(cert);
const STACK_OF(X509_EXTENSION) *allExt2 = X509_get0_extensions(certRef);
int my_idx = X509v3_get_ext_by_NID(allExt, NID_ct_precert_poison, -1);
int idx = my_idx;
#if 0
int cc = X509_get_ext_count(cert);
printf("Extension count in cert BEFORE = %d\n", cc);
//--printf((allExt==NULL) ? "Extensions extraction FAILED\n" : "Extensions extraction SUCCESS\n");
#endif
#if 0 // useless
int counter = X509v3_get_ext_count(allExt);
printf("Extension[%d] count BEFORE = %d\n", idx, counter);
#endif
#if 0
do {
X509_EXTENSION * tmpext = X509v3_get_ext(allExt, idx);
#endif
X509v3_delete_ext(allExt, idx);
#if 0
X509_EXTENSION_free(tmpext);
idx = X509v3_get_ext_by_NID(allExt, NID_ct_precert_poison, -1);
printf("pass\n");
} while (idx != -1);
printf("Extension count AFTER = %d\n", X509v3_get_ext_count(allExt));
#endif
#if 0
if(X509_cmp( cert, certRef)){
printf("Certificate modified\n\n");
} else {
printf("CENSORED \n");
}
printf("Extension count in cert AFTER = %d\n", X509_get_ext_count(cert));
#endif
#if 0 // useless
unsigned char *buf_inter = NULL;
int len_inter = i2d_X509(cert, &buf_inter);
#endif
unsigned char *dersct;
size_t lenSCTList = 0;
char *b64SCTList = "BIF6AHgAdgCwzIPlpfl9a698CcwoSQSHKsfoixMsY1C3xv0m4WxsdwAAAWZ7z/DQAAAEAwBHMEUCIQDKJPPQhWqje1rQq+T06x0iNlLT7rX71k23VPZkhm/QCwIgfhwNK7izeq0fHAlu7HuYRjmvym51RRdlNWhd50LQdu4=";
// replace mystery routine
dersct = malloc(strlen(b64SCTList)); // more than needed but convenient
lenSCTList = EVP_DecodeBlock(dersct, (unsigned char*)b64SCTList, strlen(b64SCTList));
printf("size final SCT List: %ld\n", lenSCTList);
#if 0 // useless and harmful
STACK_OF(SCT) * scts = d2i_SCT_LIST(NULL, (const unsigned char **) &dersct, lenSCTList);
if(scts==NULL){
printf("Could not convert SCT List!");
return -1;
}
printf("SCT List converted !\n");
#endif
ASN1_OCTET_STRING *val = ASN1_OCTET_STRING_new();
ASN1_OCTET_STRING_set(val, dersct, (int)lenSCTList);
free(dersct); // added
X509_EXTENSION* extSCT = X509_EXTENSION_create_by_NID(NULL, NID_ct_precert_scts, 0, val);
#if 0
if(extSCT){
printf("created extension\n");
} else {
printf("Failed to create extension\n");
return -1;
}
#endif
if( X509_add_ext(cert, extSCT, -1)) {
printf("Extension added\n");
// X509_EXTENSION_free(extSCT);
} else {
printf("failed to add extension\n");
return -1;
}
#if 0 // useless
unsigned char *buf_final = NULL;
int len_final = i2d_X509(cert, &buf_final);
#endif
// added
FILE * keyfile = fopen(argv[2],"r"); if(!keyfile) exit(2);
EVP_PKEY * signkey = PEM_read_PrivateKey (keyfile, NULL, NULL, NULL);
fclose(keyfile);
if( X509_sign(cert,signkey,EVP_sha256())<=0 ) exit(9);
BIO *Cout = BIO_new(BIO_s_mem());
PEM_write_bio_X509(Cout, cert);
char* data;
const long len = BIO_get_mem_data(Cout, &data);
printf("Extension count in cert AFTER = %d\n", X509_get_ext_count(cert));
printf("\ndata[%ld]: \n%s\n\n", len, data);
// added
FILE *outfile = fopen(argv[3],"w"); if(!outfile) exit(3);
fwrite(data,1,len,outfile); fclose(outfile);
BIO_free_all(Cout);
#if 0 // useless
int my_idx2 = X509_get_ext_by_NID(cert, NID_ct_precert_poison, -1);
X509_EXTENSION* extPoison2 = X509_get_ext(cert, my_idx2);
if(!extPoison2){
printf("failed last extension[%d] extract \n ", my_idx2);
return -1;
} else {
printf("Succeeded last extension extract[%d]\n ", my_idx2);
}
#endif
return 0;
}
However, modifying a value returned by get0 -- and 'discarding' the const on it -- is not good style, and might fail in some future implementation. It would be safer and also simpler to use X509_get_ext_by_NID and X509_delete_ext directly on cert.

Arm-Linux LCD_show_jpg picture ," Segmentation fault " problem?

I wanna show 3 .jpg pictures on LCD ,but the program crashed, it seems that the pointer did not init,here is the main() function:
#include <stdio.h>
#include <pthread.h>
int main(int argc,char **argv)
{
lcd_open("/dev/fb0");
int i = 0;
char* pic_path[3] = {"./jpeg/1.jpg","./jpeg/2.jpg","./jpeg/3.jpg"};
while(1)
{
if(i == 3)
{
i = 0;
}
lcd_draw_jpg(0, 0, pic_path[i], NULL, 0, 0);
pthread_testcancel();
sleep(1);
i++;
}
return 0;
}
It just show the 1st picture.
here is the display function Lcd.c
int lcd_draw_jpg(unsigned int x,unsigned int y,const char *pjpg_path,char *pjpg_buf,unsigned int jpg_buf_size,unsigned int jpg_half)
{
/*定义解码对象,错误处理对象*/
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
char *pcolor_buf = g_color_buf
char *pjpg
unsigned int i=0;
unsigned int color =0;
unsigned int count =0;
unsigned int x_s = x;
unsigned int x_e ;
unsigned int y_e ;
int jpg_fd;
unsigned int jpg_size;
unsigned int jpg_width;
unsigned int jpg_height;
//lcd_open("/dev/fb0");
if(pjpg_path!=NULL)
{
/* 申请jpg资源,权限可读可写 */
jpg_fd=open(pjpg_path,O_RDWR);
if(jpg_fd == -1)
{
printf("open %s error\n",pjpg_path);
return -1;
}
/* 获取jpg文件的大小 */
jpg_size=file_size_get(pjpg_path);
/* 为jpg文件申请内存空间 */
pjpg = malloc(jpg_size);
/* 读取jpg文件所有内容到内存 */
read(jpg_fd,pjpg,jpg_size);
}
else
{
jpg_size = jpg_buf_size;
pjpg = pjpg_buf;
}
/*注册出错处理*/
cinfo.err = jpeg_std_error(&jerr);
/*创建解码*/
jpeg_create_decompress(&cinfo);
/*直接解码内存数据*/
jpeg_mem_src(&cinfo,pjpg,jpg_size);
/*读文件头*/
jpeg_read_header(&cinfo, TRUE);
/*开始解码*/
jpeg_start_decompress(&cinfo);
if(jpg_half)
{
x_e = x_s+(cinfo.output_width/2);
y_e = y +(cinfo.output_height/2);
/*读解码数据*/
while(cinfo.output_scanline < cinfo.output_height)
{
pcolor_buf = g_color_buf;
/* 读取jpg一行的rgb值 */
jpeg_read_scanlines(&cinfo,(JSAMPARRAY)&pcolor_buf,1);
/* 再读取jpg一行的rgb值 */
jpeg_read_scanlines(&cinfo,(JSAMPARRAY)&pcolor_buf,1);
for(i=0; i<(cinfo.output_width/2); i++)
{
/* 获取rgb值 */
color = *(pcolor_buf+2);
color = color | *(pcolor_buf+1)<<8;
color = color | *(pcolor_buf)<<16;
/* 显示像素点 */
lcd_draw_point(x,y,color);
pcolor_buf +=6;
x++;
}
/* 换行 */
y++;
x = x_s;
}
}
else
{
x_e = x_s+cinfo.output_width;
y_e = y +cinfo.output_height;
/*读解码数据*/
while(cinfo.output_scanline < cinfo.output_height )
{
pcolor_buf = g_color_buf;
/* read one line's of jpg */
jpeg_read_scanlines(&cinfo,(JSAMPARRAY)&pcolor_buf,1);
for(i=0; i<cinfo.output_width; i++)
{
/* get rgb value */
color = *(pcolor_buf+2);
color = color | *(pcolor_buf+1)<<8;
color = color | *(pcolor_buf)<<16;
/* display pixel point */
lcd_draw_point(x,y,color);
pcolor_buf +=3;
x++;
}
/* 换行 */
y++;
x = x_s;
}
}
/*解码完成*/
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
if(pjpg_path!=NULL)
{
/* 关闭jpg文件 */
close(jpg_fd);
/* 释放jpg文件内存空间 */
free(pjpg);
}
close_lcd();
return 0;
}
this looks like Memory Leak or something else......
these seems a little weird,and

How to get rid of unresolved external errors while trying to decode audio using ffmpeg

I am trying to decode a audio file using ffmpeg, while I am doing this I am getting many unresolved external errors. I am new to ffmpeg libraries, any suggestion for the problem would be a great help.
Thank you.
void audioDecode(char* filename)
{
FILE *file;
AVFormatContext *audioInputFormatContext;
AVInputFormat *audioInputFormat = NULL;
AVCodec *audioCodec;
AVCodecContext *audioCodecContext;
av_register_all();
char *audioInputDeviceName = filename;
int ret;
int audioIndex = 0;
AVPacket pkt;
av_init_packet(&pkt);
avformat_network_init();
audioInputFormatContext = avformat_alloc_context();
ret = avformat_open_input(&audioInputFormatContext, audioInputDeviceName, audioInputFormat, NULL);
if (ret == 0)
{
ret = avformat_find_stream_info(audioInputFormatContext, 0);
if (ret >= 0)
{
for (int i = 0; i < audioInputFormatContext->nb_streams; i++) {
if (audioInputFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
audioIndex = i;
break;
}
}
audioCodec = avcodec_find_decoder(audioInputFormatContext->streams[audioIndex]->codecpar->codec_id);
audioCodecContext = avcodec_alloc_context3(audioCodec);
avcodec_parameters_to_context(audioCodecContext, audioInputFormatContext->streams[audioIndex]->codecpar);
if (avcodec_open2(audioCodecContext, audioCodec, NULL) >= 0)
{
ret = av_read_frame(audioInputFormatContext, &pkt);
AVPacket encodePacket;
AVFrame* decodeFrame = av_frame_alloc();
int dec_got_frame = 0;
if (ret == 0)
{
ret = avcodec_send_packet(audioCodecContext, &pkt);
if (ret < 0)
printf("Error");
}
ret = avcodec_receive_frame(audioCodecContext, decodeFrame);
if (ret >= 0)
dec_got_frame = 1;
if (dec_got_frame)
{
fopen_s(&file, filename, "wb");
fwrite(pkt.data, 1, pkt.size, file);
fclose(file);
}
av_frame_free(&decodeFrame);
}
}
}
avformat_close_input(&audioInputFormatContext);
avcodec_free_context(&audioCodecContext);
av_packet_unref(&pkt);
}
I'm just going to assume that you've already connected to the stream source and have the codec context by what you've mentioned in the comments.
These are snippets from my own project decoding the audio frames.
Decode the audio packet:
void FFMPEG::process_audio_packet(AVPacket *pkt) {
int got;
avcodec_decode_audio4(aud_stream.context, aud_stream.frame, &got, pkt);
if (got) Audio.add_av_frame(aud_stream.frame);
}
Process the completed frame and extract a stereo 16 bit signed buffer:
void AudioManager::add_av_frame(AVFrame *frame) {
int nsamples = frame->nb_samples;
int sample_rate = frame->sample_rate;
int channels = frame->channels;
AVSampleFormat format = (AVSampleFormat) frame->format;
bool planar = av_sample_fmt_is_planar(format) == 1;
int64_t pts = av_frame_get_best_effort_timestamp(frame);
//double ftime;
/*if (ffmpeg.vid_stream.stream_id != -1)
ftime = av_q2d(ffmpeg.aud_stream.context->time_base) * pts;
else
ftime = av_q2d(ffmpeg.vid_stream.context->time_base) * pts;*/
AudioBuffer *buffer = NULL;
if (planar) { // handle planar audio frames
/*
* PLANAR frames conversion
* ------------------------
*/
if (channels == 1) { // MONO
//LOGD("Processing PLANAR MONO");
/*
* MONO
*/
if (format == AV_SAMPLE_FMT_S16P) { // 16 bit signed
if ((buffer = alloc_buffer(frame))) { // allocated okay?
short *channel = (short*)frame->data[0];
short *buff = buffer->data;
for (int c = 0; c < nsamples; c++) {
*buff++ = *channel;
*buff++ = *channel++;
}
queue_new_buffer(buffer);
}
return;
}
if (format == AV_SAMPLE_FMT_S32P) { // 32 bit signed
if ((buffer = alloc_buffer(frame))) { // allocated okay?
int32_t *channel = (int32_t*)frame->data[0];
short *buff = buffer->data;
for (int c = 0; c < nsamples; c++) {
int16_t s = (int16_t) (*channel++ >> 16);
*buff++ = s;
*buff++ = s;
}
queue_new_buffer(buffer);
}
return;
}
if (format == AV_SAMPLE_FMT_U8P) { // 8 bit unsigned
if ((buffer = alloc_buffer(frame))) { // allocated okay?
uint8_t *channel = (uint8_t*)frame->data[0];
short *buff = buffer->data;
for (int c = 0; c < nsamples; c++) {
int16_t s = ((int16_t)(*channel++ - 128) << 8);
*buff++ = s;
*buff++ = s;
}
queue_new_buffer(buffer);
}
}
return; // scrap if no audio buffer (highly unlikely)
} else if (channels == 2) { // STEREO
//LOGD("Processing PLANAR STEREO");
/*
* STEREO
*/
if (format == AV_SAMPLE_FMT_S16P) { // 16 bit signed
if ((buffer = alloc_buffer(frame))) { // allocated okay
short *channel1 = (short*)frame->data[0];
short *channel2 = (short*)frame->data[1];
short *buff = buffer->data;
for (int c = 0; c < nsamples; c++) {
*buff++ = *channel1++;
*buff++ = *channel2++;
}
queue_new_buffer(buffer);
}
return;
}
if (format == AV_SAMPLE_FMT_S32P) { // 32 bit signed
if ((buffer = alloc_buffer(frame))) { // allocated okay?
int32_t *channel1 = (int32_t*)frame->data[0];
int32_t *channel2 = (int32_t*)frame->data[1];
short *buff = buffer->data;
for (int c = 0; c < nsamples; c++) {
int16_t s1 = (int16_t) (*channel1++ >> 16);
int16_t s2 = (int16_t) (*channel2++ >> 16);
*buff++ = s1;
*buff++ = s2;
}
queue_new_buffer(buffer);
}
return;
}
if (format == AV_SAMPLE_FMT_U8P) { // 8 bit unsigned
if ((buffer = alloc_buffer(frame))) { // allocated okay?
uint8_t *channel1 = (uint8_t*)frame->data[0];
uint8_t *channel2 = (uint8_t*)frame->data[1];
short *buff = buffer->data;
for (int c = 0; c < nsamples; c++) {
int16_t s1 = ((int16_t)(*channel1++ - 128) << 8);
int16_t s2 = ((int16_t)(*channel2++ - 128) << 8);
*buff++ = s1;
*buff++ = s2;
}
queue_new_buffer(buffer);
}
}
return;
} // TODO: Handle more channels at a later date
} else { // handle non-planar audio frames
/*
* INTERLEAVED conversion
* ----------------------
*/
}
}
Process the audio buffer:
void AudioManager::queue_new_buffer(AudioBuffer *buffer) {
if (buffer) { // valid buffer
// apply volume gain (only working with stereo)
if (volume != 100) {
short *data = buffer->data;
int num_samples = buffer->nsamples << 1;
while (num_samples--) {
long sample = ((long)*data * volume) / 100;
if (sample < -32768) sample = -32768;
if (sample > 32767) sample = 32767;
*data++ = (short)sample;
}
}
// add buffer to queue
buffer->used = true;
double pts_start = get_pts_start_time();
decode_pos = (++decode_pos) % MAX_AUD_BUFFERS;
if (decode_pos == playback_pos)
playback_pos = (++playback_pos) % MAX_AUD_BUFFERS;
if (ffmpeg.vid_stream.stream_id == -1 && pts_start < 0.0) {
set_pts_start_time(buffer->frame_time);
set_sys_start_time(Display.get_current_render_time());
LOGD("START TIME FROM AUDIO STREAM...");
}
//LOGI("Audio buffer queued %d (%d)", decode_pos, playback_pos);
}
}

Berkeley DB works slowly after I hooked the recv function of mongoose

what I am doing is a little bit tricky. I tried to hook the recv function of mongoose using LD_PRELOAD. After mongoose receives a request, it will first of all store this request into Berkeley DB and then proceed. However, I found that the storing speed of Berkeley DB is much slower than usual. Storing the same size of contents, an independent program only takes 1000 nanoseconds, but the hooked mongoose can take up to 20 milliseconds. I totally have no idea how this could happen. Any help would be appreciated.
typedef uint32_t req_id_t;
typedef uint32_t view_id_t;
typedef struct view_stamp_t{
view_id_t view_id;
req_id_t req_id;
}view_stamp;
typedef struct db_t{
DB* bdb_ptr;
}db;
#define BILLION 1000000000L
const char* db_dir="./.db";
uint64_t vstol(view_stamp vs){
uint64_t result = ((uint64_t)vs.req_id)&0xFFFFFFFFl;
uint64_t temp = (uint64_t)vs.view_id&0xFFFFFFFFl;
result += temp<<32;
return result;
};
void mk_path(char* dest,const char* prefix,const char* db_name){
memcpy(dest,prefix,strlen(prefix));
dest[strlen(prefix)] = '/';
memcpy(dest+strlen(prefix)+1,db_name,strlen(db_name));
dest[strlen(prefix)+strlen(db_name)+1] = '\0';
return;
}
db* initialize_db(const char* db_name,uint32_t flag)
{
db* db_ptr=NULL;
DB* b_db;
DB_ENV* dbenv;
int ret;
char* full_path = NULL;
if((ret=mkdir(db_dir,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH))!=0){
if(errno!=EEXIST){
goto db_init_return;
}
}
full_path = (char*)malloc(strlen(db_dir) + strlen(db_name)+2);
mk_path(full_path,db_dir,db_name);
if ((ret = db_env_create(&dbenv,0)) != 0) {
dbenv->err(dbenv, ret, "Environment Created: %s", db_dir);
goto db_init_return;
}
if ((ret = dbenv->open(dbenv,db_dir,DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL|DB_THREAD, 0)) != 0) {
goto db_init_return;
}
/* Initialize the DB handle */
if((ret = db_create(&b_db,dbenv,flag))!=0){
goto db_init_return;
}
if((ret = b_db->open(b_db,NULL,db_name,NULL,DB_BTREE,DB_THREAD|DB_CREATE,0))!=0){
goto db_init_return;
}
db_ptr = (db*)(malloc(sizeof(db)));
db_ptr->bdb_ptr = b_db;
db_init_return:
if(full_path!=NULL){
free(full_path);
}
return db_ptr;
}
int store_record(db* db_p, size_t key_size, void* key_data, size_t data_size, void* data){
int ret = 1;
if((NULL == db_p)||(NULL == db_p->bdb_ptr)){
if(db_p == NULL){
printf("DB store_record : db_p is null.\n");
} else{
printf("DB store_recor : db_p->bdb_ptr is null.\n");
}
goto db_store_return;
}
DB* b_db = db_p->bdb_ptr;
DBT key,db_data;
memset(&key, 0, sizeof(key));
memset(&db_data, 0, sizeof(db_data));
key.data = key_data;
key.size = key_size;
db_data.data = data;
db_data.size = data_size;
struct timespec start, end;
uint64_t diff;
clock_gettime(CLOCK_MONOTONIC, &start);
if ((ret = b_db->put(b_db,NULL,&key,&db_data,0)) == 0){
}
else{
printf("DB : %s.\n", db_strerror(ret));
}
clock_gettime(CLOCK_MONOTONIC, &end);
diff = BILLION * (end.tv_sec - start.tv_sec) + end.tv_nsec - start.tv_nsec;
printf("elapsed time = %llu nanoseconds\n", (long long unsigned int) diff);
db_store_return:
return ret;
}
int i = 1;
view_stamp vs;
db* db_ptr;
ssize_t recv(int sockfd, void *buf, size_t len, int flags)
{
if (i == 1)
{
db_ptr = initialize_db("node_test",0);
vs.view_id = 0;
vs.req_id = 0;
}
i = 0;
typedef ssize_t (*orig_recv_type)(int, void *, size_t, int);
orig_recv_type orig_recv;
orig_recv = (orig_recv_type) dlsym(RTLD_NEXT, "recv");
ssize_t ret = orig_recv(sockfd, buf, len, flags);
vs.req_id++;
uint64_t record_no = vstol(vs);
store_record(db_ptr, sizeof(record_no), &record_no, ret, buf);
return ret;
}

Resources