ffmpeg Resource temporarily unavailable - c

I'm trying to encode an audio frame using ffmpeg library and Opus codec
but i faced with this error :
Resource temporarily unavailable
My source code :
void encode_audio(uint8_t *frame , int frame_size , void (*onPacket)(uint8_t *packet , int packet_size)){
if(audio_encoder_codec_context != NULL){
memset(audio_encoder_frame_buffer , 0 , (size_t) audio_encoder_frame_size);
swr_convert(
s16_to_flt_resampler,
&audio_encoder_frame_buffer,
audio_encoder_frame_size,
(const uint8_t **) &frame,
frame_size
);
int result = avcodec_send_frame(audio_encoder_codec_context , audio_encoder_frame);
while(result >= 0){
result = avcodec_receive_packet(audio_encoder_codec_context , audio_encoder_packet);
char *a = malloc(1024);
av_strerror(result , a , 1024);
printf("%s\n",a);
if (result == AVERROR(EAGAIN) || result == AVERROR_EOF || result < 0){
break;
}
onPacket(audio_encoder_packet->data , audio_encoder_packet->size);
av_packet_unref(audio_encoder_packet);
}
}
}

This is coming from AVERROR(EAGAIN).
You should send more frames when AVERROR(EAGAIN) is returned.
Docs state this for avcodec_receive_packet
avcodec.h:
/**
* Read encoded data from the encoder.
*
* #param avctx codec context
* #param avpkt This will be set to a reference-counted packet allocated by the
* encoder. Note that the function will always call
* av_packet_unref(avpkt) before doing anything else.
* #return 0 on success, otherwise negative error code:
* AVERROR(EAGAIN): output is not available in the current state - user
* must try to send input
* AVERROR_EOF: the encoder has been fully flushed, and there will be
* no more output packets
* AVERROR(EINVAL): codec not opened, or it is a decoder
* other errors: legitimate encoding errors
*/
int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
Depending on the data, FFmpeg can require additional input/data before output can be produced.
More from the docs:
AVERROR(EAGAIN): output is not available in the current state - user must try to send input.
Keep giving it data until you get a return code of 0 (success).

Related

How to write log files correctly?

How to reliably record logs to be sure of the atomicity of entries in multi-threaded applications? In addition, I would like to be able to rotate logs using the logrotate utility.
The simplest variant to write logs is next:
open/reopen log file
write entries by printf()
close log file at exit
Here is my example:
// default log level
static Cl_loglevl loglevel = LOGLEVEL_NONE;
// log file descriptor (open with Cl_openlog)
static FILE *logfd = NULL;
/**
* #brief Cl_openlog - open log file
* #param logfile - file name
* #return FILE struct or NULL if failed
*/
FILE *Cl_openlog(const char *logfile, Cl_loglevl loglvl){
if(logfd){
Cl_putlog(LOGLEVEL_ERROR, "Reopen log file\n");
fclose(logfd);
logfd = NULL;
char newname[PATH_MAX];
snprintf(newname, PATH_MAX, "%s.old", logfile);
if(rename(logfile, newname)) WARN("Can't rename old log file");
}
if(loglvl < LOGLEVEL_CNT) loglevel = loglvl;
if(!logfile) return NULL;
if(!(logfd = fopen(logfile, "w"))) WARN(_("Can't open log file"));
return logfd;
}
/**
* #brief Cl_putlog - put message to log file
* #param lvl - message loglevel (if lvl > loglevel, message won't be printed)
* #param fmt - format and the rest part of message
* #return amount of symbols saved in file
*/
int Cl_putlog(Cl_loglevl lvl, const char *fmt, ...){
if(lvl > loglevel || !logfd) return 0;
char strtm[128];
time_t t = time(NULL);
struct tm *curtm = localtime(&t);
strftime(strtm, 128, "%Y/%m/%d-%H:%M", curtm);
int i = fprintf(logfd, "%s\t", strtm);
va_list ar;
va_start(ar, fmt);
i += vfprintf(logfd, fmt, ar);
va_end(ar);
fflush(logfd);
return i;
}
The call of Cl_openlog allows to rotate log once. I can call this function in SIG_USR1 handler and send this signal by logrotate. But it still remains unclear how to write to a file correctly in order to achieve atomicity of records.
I don't want to use external libraries like log4c for such simple problem.
Either you can assure that all logging is done through a single thread, or you protect logging function with mutexes.
For first case, you can have a worker thread that polls on a pipe's read-end; then each thread will use pipe's write-end to wakeup worker thread and let it manage its log (allocated somewhere on heap and passed by address through pipe).
The same can be done for your SIGUSR1 handler (logrotate).
Please note that writing less than PIPE_BUF to a pipe() is guaranteed not to be interleaved (thus it is atomic).
Consequently writing just an heap storage address will always be atomic.
Last but not least, you may use different logfiles for each thread.
Well, at last I did this:
// array with all opened logs - for error/warning messages
static Cl_log *errlogs = NULL;
static int errlogsnum = 0;
/**
* #brief Cl_createlog - create log file: init mutex, test file open ability
* #param log - log structure
* #return 0 if all OK
*/
int Cl_createlog(Cl_log *log){
if(!log || !log->logpath || log->loglevel <= LOGLEVEL_NONE || log->loglevel >= LOGLEVEL_CNT) return 1;
FILE *logfd = fopen(log->logpath, "a");
if(!logfd){
WARN("Can't open log file");
return 2;
}
fclose(logfd);
pthread_mutex_init(&log->mutex, NULL);
errlogs = realloc(errlogs, (++errlogsnum) *sizeof(Cl_log));
if(!errlogs) errlogsnum = 0;
else memcpy(&errlogs[errlogsnum-1], log, sizeof(Cl_log));
return 0;
}
/**
* #brief Cl_putlog - put message to log file with/without timestamp
* #param timest - ==1 to put timestamp
* #param log - pointer to log structure
* #param lvl - message loglevel (if lvl > loglevel, message won't be printed)
* #param fmt - format and the rest part of message
* #return amount of symbols saved in file
*/
int Cl_putlogt(int timest, Cl_log *log, Cl_loglevl lvl, const char *fmt, ...){
if(!log || !log->logpath || log->loglevel < 0 || log->loglevel >= LOGLEVEL_CNT) return 0;
if(lvl > log->loglevel) return 0;
if(pthread_mutex_lock(&log->mutex)) return 0;
int i = 0;
FILE *logfd = fopen(log->logpath, "a");
if(!logfd) goto rtn;
if(timest){
char strtm[128];
time_t t = time(NULL);
struct tm *curtm = localtime(&t);
strftime(strtm, 128, "%Y/%m/%d-%H:%M", curtm);
i = fprintf(logfd, "%s\t", strtm);
}
va_list ar;
va_start(ar, fmt);
i += vfprintf(logfd, fmt, ar);
va_end(ar);
fclose(logfd);
rtn:
pthread_mutex_unlock(&log->mutex);
return i;
}
In Cl_createlog() I just test ability of opening of given file and init mutex. In Cl_putlogt() I open given file, write to it and close it. The mutex used to make writing atomic for any threads.
The array errlogs consists all opened logs for writing critical messages.

FFMPEG remux sample without writing to file

Let's consider this very nice and easy to use remux sample by horgh.
I'd like to achieve the same task: convert an RTSP H264 encoded stream to a fragmented MP4 stream.
This code does exactly this task.
However I don't want to write the mp4 onto disk at all, but I need to get a byte buffer or array in C with the contents that would normally written to disk.
How is that achievable?
This sample uses vs_open_output to define the output format and this function needs an output url.
If I would get rid of outputting the contents to disk, how shall I modify this code?
Or there might be better alternatives as well, those are also welcomed.
Update:
As szatmary recommended, I have checked his example link.
However as I stated in the question I need the output as buffer instead of a file.
This example demonstrates nicely how can I read my custom source and give it to ffmpeg.
What I need is how can open the input as standard (with avformat_open_input) then do my custom modification with the packets and then instead writing to file, write to a buffer.
What have I tried?
Based on szatmary's example I created some buffers and initialization:
uint8_t *buffer;
buffer = (uint8_t *)av_malloc(4096);
format_ctx = avformat_alloc_context();
format_ctx->pb = avio_alloc_context(
buffer, 4096, // internal buffer and its size
1, // write flag (1=true, 0=false)
opaque, // user data, will be passed to our callback functions
0, // no read
&IOWriteFunc,
&IOSeekFunc
);
format_ctx->flags |= AVFMT_FLAG_CUSTOM_IO;
AVOutputFormat * const output_format = av_guess_format("mp4", NULL, NULL);
format_ctx->oformat = output_format;
avformat_alloc_output_context2(&format_ctx, output_format,
NULL, NULL)
Then of course I have created 'IOWriteFunc' and 'IOSeekFunc':
static int IOWriteFunc(void *opaque, uint8_t *buf, int buf_size) {
printf("Bytes read: %d\n", buf_size);
int len = buf_size;
return (int)len;
}
static int64_t IOSeekFunc (void *opaque, int64_t offset, int whence) {
switch(whence){
case SEEK_SET:
return 1;
break;
case SEEK_CUR:
return 1;
break;
case SEEK_END:
return 1;
break;
case AVSEEK_SIZE:
return 4096;
break;
default:
return -1;
}
return 1;
}
Then I need to write the header to the output buffer, and the expected behaviour here is to print "Bytes read: x":
AVDictionary * opts = NULL;
av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
av_dict_set_int(&opts, "flush_packets", 1, 0);
avformat_write_header(output->format_ctx, &opts)
In the last line during execution, it always runs into segfault, here is the backtrace:
#0 0x00007ffff7a6ee30 in () at /usr/lib/x86_64-linux-gnu/libavformat.so.57
#1 0x00007ffff7a98189 in avformat_init_output () at /usr/lib/x86_64-linux-gnu/libavformat.so.57
#2 0x00007ffff7a98ca5 in avformat_write_header () at /usr/lib/x86_64-linux-gnu/libavformat.so.57
...
The hard thing for me with the example is that it uses avformat_open_input.
However there is no such thing for the output (no avformat_open_ouput).
Update2:
I have found another example for reading: doc/examples/avio_reading.c.
There are mentions of a similar example for writing (avio_writing.c), but ffmpeg does not have this available (at least in my google search).
Is this task really this hard to solve? standard rtsp input to custom avio?
Fortunately ffmpeg.org is down. Great.
It was a silly mistake:
In the initialization part I called this:
avformat_alloc_output_context2(&format_ctx, output_format,
NULL, NULL)
However before this I already put the avio buffers into format_ctx:
format_ctx->pb = ...
Also, this line is unnecessary:
format_ctx = avformat_alloc_context();
Correct order:
AVOutputFormat * const output_format = av_guess_format("mp4", NULL, NULL);
avformat_alloc_output_context2(&format_ctx, output_format,
NULL, NULL)
format_ctx->pb = avio_alloc_context(
buffer, 4096, // internal buffer and its size
1, // write flag (1=true, 0=false)
opaque, // user data, will be passed to our callback functions
0, // no read
&IOWriteFunc,
&IOSeekFunc
);
format_ctx->flags |= AVFMT_FLAG_CUSTOM_IO;
format_ctx->oformat = output_format; //might be unncessary too
Segfault is gone now.
You need to write a AVIOContext implementation.

libjpeg turbo tjCompressFromYUV

I'd like to compress a planar 4:2:0 YUV buffer to a jpeg image using libturbojpeg in C, but I'm having trouble using the tjCompressFromYUV() function.
This is my code:
#define PADDING 2
tjhandle tjh;
unsigned long buf_size;
unsigned char *jpegBuf = NULL;
unsigned long jpegSize;
int width = 352;
int height = 288;
int quality = 70;
unsigned char *ucp_frame;
int j;
FILE *fp = NULL;
ucp_frame = malloc(width * height * 3 / 2);
if ( NULL == ucp_frame ) {
printf("malloc error ucp_frame\n");
return 0;
}
fp = fopen("planar_352x288.raw", "rb");
if( NULL == fp ) {
printf("fopen error\n");
return 0;
}
j = fread( ucp_frame, 1, width * height * 3 / 2, fp);
if( j != width * height * 3 / 2 ) {
printf("fread error\n");
return 0;
}
fclose(fp);
tjh = tjInitCompress();
if( NULL == tjh ) {
printf("tjInitCompress error '%s'\n", tjGetErrorStr() );
return 0;
}
buf_size = tjBufSizeYUV2( width, PADDING, height, TJSAMP_420);
jpegBuf = tjAlloc(buf_size);
if( tjCompressFromYUV( tjh, ucp_frame, width, PADDING, height,
TJSAMP_420, &jpegBuf, &jpegSize, quality,
TJFLAG_NOREALLOC ) ) {
printf("tjCompressFromYUV error '%s'\n", tjGetErrorStr() );
}
The error string returned by tjGetErrorStr() is "Bogus input colorspace".
I tried linking libturbojpeg versions 1.4.2 and 1.4.90.
Any help wolud be appreciated,
Thanks
Turbojpeg API tjCompressFromYUV allows you such options for jpegBuf:
#param jpegBuf address of a pointer to an image buffer that will receive the
JPEG image. TurboJPEG has the ability to reallocate the JPEG buffer to
accommodate the size of the JPEG image. Thus, you can choose to:
pre-allocate the JPEG buffer with an arbitrary size using #tjAlloc() and
let TurboJPEG grow the buffer as needed,
set *jpegBuf to NULL to tell TurboJPEG to allocate the buffer
for you, or
pre-allocate the buffer to a "worst case" size determined by calling
tjBufSize(). This should ensure that the buffer never has to be
re-allocated (setting #TJFLAG_NOREALLOC guarantees this.)
If you choose option 1, *jpegSize should be set to the size of your
pre-allocated buffer. In any case, unless you have set #TJFLAG_NOREALLOC,
you should always check *jpegBuf upon return from this function, as
it may have changed.
So by using 2-nd option, there is no need to call tjBufSizeYUV2 and tjAlloc, simply have jpegBuf=NULL before calling tjCompressFromYUV and do tjFree after compressing.
Ok it turned out the problem was in the program containing the code I posted, in a smaller test program the tjBufSizeYUV2 call performs as expected.
On a side note it seems that if jpegBuf is pre-allocated before calling tjBufSizeYUV2, the flag argument passed to tjBufSizeYUV2 must contain TJFLAG_NOREALLOC, or else jpegBuf won't be freed even if tjFree(jpegBuf); is later called.
#define PADDING 4
jpegBuf = tjAlloc(width*height*3/2);

HTTP protocol: end of a message body

I built a program that parses the header and I would like to read the message body in case I receive a POST.
For headers, I have been able to look for to determine when the header ends. I am having more issues for the message body. Am I supposed to look at "Content-Length" field to know when to stop reading input? In my current code (below), it will not stop until I hit the red cross (stop loading page) in Firefox.
Here is the code:
size_t n;
unsigned char newChar;
int index = 0;
int capacity = 50;
char *option = (char *) malloc(sizeof(char) * capacity);
while ( ( n = read( req->socket, &newChar, sizeof(newChar) ) ) > 0 ) {
if (newChar == '\0' || newChar == '\n') break; // This is not working
if (index == capacity) {
capacity *= 2;
option = (char *) realloc(option, sizeof(char) * capacity);
assert(option != NULL);
}
option[index++] = newChar;
fprintf(stderr, "%c", newChar);
}
if (index == capacity) {
capacity *= 2;
option = (char *) realloc(option, sizeof(char) * capacity);
assert(option != NULL);
}
option[index] = '\0';
The correct input gets printed, but I wonder why it won't stop until the stop loading button get pressed. I'd like to know if there is any other solution or if I please need to use the "Content-Length" field in the header.
Thank you very much,
Jary
There are a few things to consider. You'll want to consider how you want to handle all of these cases perhaps?
For HTTP protocol 1.0 the connection closing was used to signal the end of data.
This was improved in HTTP 1.1 which supports persistant connections. For HTTP 1.1 typically you set or read the Content-Length header to know how much data to expect.
Finally with HTTP 1.1 there is also the possibility of "Chunked" mode, you get the size as they come and you know you've reached the end when a chunk Size == 0 is found.
Also do you know about libcurl? It will certainly help you having to re-implement the wheel.
This code blocks on the read() waiting for another character which never comes.
Additionally, RFC2616, 3.7.1 states "HTTP applications MUST accept CRLF, bare CR, and bare LF as being representative of a line break in text media received via HTTP. In addition, if the text is represented in a character set that does not use octets 13 and 10 for CR and LF respectively, as is the case for some multi-byte character sets, HTTP allows the use of whatever octet sequences are defined by that character set to represent the equivalent of CR and LF for line breaks."
So you're going to need to catch more than just "\n".

Sybase error while fetching columns more then 255 characters

I'm having problems while fetching data from columns which have more than 255 characters
I got such an error message:
Open Client Message:
Message number: LAYER = (1) ORIGIN = (4) SEVERITY = (1) NUMBER = (132)
Message String: ct_fetch(): user api layer: internal common library error: The bind of result set item 3 resulted in truncation.
It fetches only the first 255 rows and truncates the rest.
I have tried to imply below lines before ct_connect but didn't work
CS_BOOL boolv = CS_TRUE;
CS_RETCODE retcode2 = ct_capability ( *connection, CS_GET, CS_CAP_REQUEST, CS_WIDETABLES, &boolv);
here are some part of the code , do you have any suggestion
for (i = 0; i < num_cols; i++) {
/*
** Get the column description. ct_describe() fills the
** datafmt parameter with a description of the column.
*/
retcode = ct_describe(cmd, (i + 1), &datafmt[i]);
if (retcode != CS_SUCCEED) {
ex_error("ex_fetch_data: ct_describe() failed");
break;
}
/*
** update the datafmt structure to indicate that we want the
** results in a null terminated character string.
**
** First, update datafmt.maxlength to contain the maximum
** possible length of the column. To do this, call
** ex_display_len() to determine the number of bytes needed
** for the character string representation, given the
** datatype described above. Add one for the null
** termination character.
*/
datafmt[i].maxlength = ex_display_dlen(&datafmt[i]) + 1;
/*
** Set datatype and format to tell bind we want things
** converted to null terminated strings
*/
datafmt[i].datatype = CS_LONGCHAR_TYPE;
datafmt[i].format = CS_FMT_NULLTERM;
/*
** Allocate memory for the column string
*/
coldata[i].value = (CS_CHAR *) malloc(datafmt[i].maxlength);
if (coldata[i].value == NULL) {
ex_error("ex_fetch_data: malloc() failed");
retcode = CS_MEM_ERROR;
break;
}
/*
** Now bind.
*/
retcode = ct_bind(cmd, (i + 1), &datafmt[i], coldata[i].value,
&coldata[i].valuelen, (CS_SMALLINT *) &coldata[i].indicator);
if (retcode != CS_SUCCEED) {
ex_error("ex_fetch_data: ct_bind() failed");
break;
}
}
.............
.............
.............
/*
** Fetch the rows. Loop while ct_fetch() returns CS_SUCCEED or
** CS_ROW_FAIL
*/
while (((retcode = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED,
&rows_read)) == CS_SUCCEED) || (retcode == CS_ROW_FAIL)) {
Even we have faced problem when we are using Sybase with Uniface,but uniface sybase driver has got a option which will truncate the data and save in some other table but while fetching we have to fetch data from all the tables.
When using the native jconn*.jar drivers you have to set the "?CHARSET=iso_1" parameter on the JDBC driver to connect to a Sybase server with a default charset of Roman 8, otherwise you see this 255 characters truncation issue.
Could this be the problem you are experiencing?

Resources