call ff_print_debug_info2 outside of mpegvideo.c file - c

I want void ff_print_debug_info2(...) to be called outside of mpegvideo.c file. For instance, I want to call this function inside the following code snippet:
static int decode_packet(int *got_frame, int cached)
{
int ret = 0;
int decoded = pkt.size;
*got_frame = 0;
if (pkt.stream_index == video_stream_idx) {
/* decode video frame */
ret = avcodec_decode_video2(video_dec_ctx, frame, got_frame, &pkt);
if (ret < 0) {
fprintf(stderr, "Error decoding video frame (%s)\n", av_err2str(ret));
return ret;
}
if (*got_frame) {
/*here I want to print debug info*/
//void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_table, uint32_t *mbtype_table, int8_t *qscale_table, int16_t (*motion_val[2])[2], int *low_delay, int mb_width, int mb_height, int mb_stride, int quarter_sample)
}
}
return decoded;
}
I wonder if it's possible, and how shall I pass parameters into void ff_print_debug_info2(...)?
ps: parameters I already know:
1.AVCodecContext *avctx: video_dec_ctx
2.AVFrame *pict: frame
3.int8_t *qscale_table: frame->qscale_table.
How about the others?

This function is already called for you by the H264 decoder. It is unsupported by any other decoder and will cause crashes. You should never need to call it manually. If you're not seeing any debug information printed on the frame after H264 frame decoding, try to use:
avctx->debug |= FF_DEBUG_VIS_QP |
FF_DEBUG_VIS_MB_TYPE |
FF_DEBUG_SKIP |
FF_DEBUG_QP |
FF_DEBUG_MB_TYPE;
avctx->debug_mv = FF_DEBUG_VIS_MV_P_FOR |
FF_DEBUG_VIS_MV_B_FOR |
FF_DEBUG_VIS_MV_B_BACK;
after (thanks for the correction!) your call to avcodec_open2(). After that, you should see the appropriate debug information printed on the frame (*_VIS_*) or on the terminal (the others).
These flags are also supported by the MPEG-1/2/4 decoders, although they are implemented through a different function (ff_print_debug_info()).

As you can see on the manual you can use outside mpegvideo.c scope.
The function ff_print_debug_info2 is exported with mpegvideo.h
So just
#include <mpegvideo.h>
or
#include "mpegvideo..h"
in source file where function has to be used.

Related

How can a callback function be executed within a driver on linux?

I have to modify a driver that runs on linux to add a callback function that is invoked from an external application. I already have the code implemented but when it is executed when the computer starts up, the system gives an error and is blocked.
This is my new code on the driver side:
typedef void (*callbackFunctionNoParams) ();
typedef struct T_EXI_CONFIGURE_BUS_
{
T_mode mode;
unsigned short NumeroRT;
T_SA_Enable SA_Enable;
unsigned short MINOR_CYCLE;
callbackFunctionNoParams callback;
} T_EXI_CONFIGURE_BUS;
typedef struct PciExiDev_
{
/**
* It represents a char device to read/write
*/
struct cdev charDevice;
/**
* IRQ assigned
*/
unsigned int irq;
/**
* Callback function to be invoked
*/
callbackFunctionNoParams callback;
/**
* Device control block
*/
EXI_DCB theDCB;
} PciExiDev;
Execution code on driver side:
static long exi_ioctl( struct file * filep, unsigned int cmd, unsigned long arg )
{
PciExiDev * aPciExiDev = (PciExiDev *) filep->private_data;
int result = SUCCESS;
int i, j;
long ret = 0;
//printk("Ioctl received %d.\n",cmd);
switch( cmd )
{
case FIO_EXI_CONFIGURE_BUS:
{
T_EXI_CONFIGURE_BUS config;
T_LISTA_TRANS *auxTrans1, *auxTrans2;
T_TRANSACTION_DCB *transDCB1;
T_OPI opi;
T_EXIS exis;
unsigned short dato;
unsigned short datolong[2];
unsigned short ControlBlock[12];
// printk("Exi configure bus initiated.\n");
printk("TNB. Exi ioctl CONFIGURE BUS.\n");
copy_from_user( &config, (T_EXI_CONFIGURE_BUS *) arg, sizeof(T_EXI_CONFIGURE_BUS) );
LeerDatos( &aPciExiDev->theDCB, OPI_ADDRESS, 1, (unsigned short *) &opi, 1 );
aPciExiDev->callback = config.callback;
aPciExiDev->theDCB.modo = config.mode;
aPciExiDev->theDCB.CicloMenor = config.MINOR_CYCLE;
(*aPciExiDev->callback)();
...
New code on client side:
if( theHWConfiguration.existExi() )
{
T_EXI_CONFIGURE_BUS bus_config;
// Configura la tarjega exi en modo Bus Controller.
bus_config.mode = BC;
bus_config.NumeroRT = 28;
bus_config.MINOR_CYCLE = 20;
bus_config.callback = &bcInterruptHandler2;
status = ioctl( A_fd_exi, FIO_EXI_CONFIGURE_BUS, reinterpret_cast<long>( &bus_config ) );
}
return status;
}
void C_EXI::bcInterruptHandler2()
{
std::cout<< "bcInterruptHandler2" << endl;
}
And this is the execution code result:
Crash Image
If someone could help me or propose an alternative way of doing this I would be very grateful.
Your callback is bound to run at kernel space and then you write it to std::cout. While going through your code, it tells that there is a conflict between kernel mode address space and userside process address space. This means that if the callback function is declared in the userside but instead called in the kernel space, there would be an error.
The crash image suggests that somewhere in your code you have an invalid pointer that you are trying to access. I am afraid I cannot debug your code with the little context provided, but I can give you some suggestions:
Try to avoid casting until is strictly necessary.
When you are casting to a pointer, double-check that this is exactly what you need to do.
In the error message there is also the call stack: take a look at it in order to identify where is the error.
You can simply add some printk("%p", pointer) in your code to debug the content of your variables.

C unused pointer parameter

I have found the following function definition in Linux source:
static int __ref kernel_init(void *unused)
{
int ret;
kernel_init_freeable();
/* need to finish all async __init code before freeing the memory */
async_synchronize_full();
ftrace_free_init_mem();
free_initmem();
mark_readonly();
/*
* Kernel mappings are now finalized - update the userspace page-table
* to finalize PTI.
*/
pti_finalize();
system_state = SYSTEM_RUNNING;
numa_default_policy();
rcu_end_inkernel_boot();
if (ramdisk_execute_command) {
ret = run_init_process(ramdisk_execute_command);
if (!ret)
return 0;
pr_err("Failed to execute %s (error %d)\n",
ramdisk_execute_command, ret);
}
/*
* We try each of these until one succeeds.
*
* The Bourne shell can be used instead of init if we are
* trying to recover a really broken machine.
*/
if (execute_command) {
ret = run_init_process(execute_command);
if (!ret)
return 0;
panic("Requested init %s failed (error %d).",
execute_command, ret);
}
if (!try_to_run_init_process("/sbin/init") ||
!try_to_run_init_process("/etc/init") ||
!try_to_run_init_process("/bin/init") ||
!try_to_run_init_process("/bin/sh"))
return 0;
panic("No working init found. Try passing init= option to kernel. "
"See Linux Documentation/admin-guide/init.rst for guidance.");
}
My question concerns the unused argument to the function. I have seen some other questions where one can use the GCC attribute specifier to declare the argument as unused and some other techniques, but this one looks like it would generate some weird compiler warnings since I see no usage of any suppression techniques here. Does anyone know what is the use of this argument here?
The unused parameter is there, because kernel_init is run as a kernel_thread which expects a pointer to int(void*) function as the first argument.
From here:
pid = kernel_thread(kernel_init, NULL, CLONE_FS);

How to send messages in PM server Minix

So I'm trying to create a new system call on PM server. My question is, how can I send some kind of message to function.
in IPC server all I had to do is add my system call to the list, because all functions there were defined as (*func)(message *)
(...)/servers/ipc/main.c
static struct {
int type;
int (*func)(message *);
int reply; /* whether the reply action is passed through */
} ipc_calls[] = {
(...)
{ IPC_MYNEWSIGNAL, do_something, 1 },
};
but in PM in table.c functions are defined as
(...)/servers/pm/table.c
int (* const call_vec[NR_PM_CALLS])(void) = {
(...)
CALL(PM_GETSYSINFO) = do_getsysinfo
}
and if I try to pass function with signature
int do_something(message *m)
I will get error:
Incompatible pointer types: initializing int (*const)(void) with int (message *)
What is the correct way to create signal on PM server if I need to receive some kind of information?
As far as I understood from the question, you want to receive arguments inside the syscall handler. Let's take as an example the library function clock_settime from libc.
int clock_settime(clockid_t clock_id, const struct timespec *ts)
{
message m;
memset(&m, 0, sizeof(m));
m.m_lc_pm_time.clk_id = clock_id;
m.m_lc_pm_time.now = 1; /* set time immediately. don't use adjtime() method. */
m.m_lc_pm_time.sec = ts->tv_sec;
m.m_lc_pm_time.nsec = ts->tv_nsec;
if (_syscall(PM_PROC_NR, PM_CLOCK_SETTIME, &m) < 0)
return -1;
return 0;
}
As you can see it writes the args inside message struct and passes to _syscall. OK, now have a look at syscall handler for PM_CLOCK_SETTIME which is mounted in table.c.
int do_gettime()
{
clock_t ticks, realtime, clock;
time_t boottime;
int s;
if ( (s=getuptime(&ticks, &realtime, &boottime)) != OK)
panic("do_time couldn't get uptime: %d", s);
switch (m_in.m_lc_pm_time.clk_id) {
case CLOCK_REALTIME:
clock = realtime;
break;
case CLOCK_MONOTONIC:
clock = ticks;
break;
default:
return EINVAL; /* invalid/unsupported clock_id */
}
mp->mp_reply.m_pm_lc_time.sec = boottime + (clock / system_hz);
mp->mp_reply.m_pm_lc_time.nsec =
(uint32_t) ((clock % system_hz) * 1000000000ULL / system_hz);
return(OK);
}
It becomes clear that the argument is a global variable named m_in. A little bit more search shows that it comes from glo.h
/* The parameters of the call are kept here. */
EXTERN message m_in; /* the incoming message itself is kept here. */
I suppose that MINIX will handle setting and accessing the global variable, so you don't need to explicitly write to it.
Have a look at point 7 Passing a parameter to a system call here. To understand how to compile the kernel correctly refer to this post.

Using function inside a call back in different function

I'm working on USB CDC on ATSAMD21. The code which i'm using is ATMEL START example for USB CD Echo on D21. I'm working on atmel studio.
Requirement:
In my application the host send data to the device and i need to read that data and send back different data to the host from different function.
Here in echo example the data reception and transfer is using the call back. I'm not aware how to use a write call inside another function. Here i'm attaching the code below
Read & Echo the data:
Here in this function it is for read the data and echo it back to the host.
static bool usb_device_cb_state_c(usb_cdc_control_signal_t state)
{
if (state.rs232.DTR ) {
/* Callbacks must be registered after endpoint allocation */
cdcdf_acm_register_callback(CDCDF_ACM_CB_READ, (FUNC_PTR)usb_device_cb_bulk_out);
cdcdf_acm_register_callback(CDCDF_ACM_CB_WRITE, (FUNC_PTR)usb_device_cb_bulk_in);
/* Start Rx */
cdcdf_acm_read((uint8_t *)usbd_cdc_buffer, sizeof(usbd_cdc_buffer));
}
/* No error. */
return false;
}
/////////////////////////////////////
Read the data from host:
static bool usb_device_cb_bulk_out(const uint8_t ep, const enum
usb_xfer_code rc, const uint32_t count)
{
cdcdf_acm_write((uint8_t *)usbd_cdc_buffer, count);
return false;
}
Write back the data:
static bool usb_device_cb_bulk_in(const uint8_t ep, const enum usb_xfer_code rc, const uint32_t count)
{
/* Echo data. */
cdcdf_acm_read((uint8_t *)usbd_cdc_buffer, sizeof(usbd_cdc_buffer));
/* No error. */
return false;
}
I need to use this read call inside another function outside. I used the read call directly in another function, it was not able to send the data.
How can i make this call use in another function.Any help will be appreciated.
Here the callback will direct to the read and write functions.
This is a fun one!
From the main loop, using a stack allocated char buffer:
const char hello[] = "Hi There!\r\n";
cdcdf_acm_write((void*)hello, 11);
works for me, but curiously using a pointer to a string constant:
const char* hello = "Hi There!\r\n";
cdcdf_acm_write((void*)hello, 11);
does not output anything! Similarly, a static const buffer
const char hello[] = "Hi There!\r\n";
int main(void)
{
// init ...
while (1)
{
delay_ms(200);
cdcdf_acm_write((void*)hello, 11);
}
}
doesn't work either, but a non-const static buffer:
char hello[] = "Hi There!\r\n";
int main(void)
{
// init ...
while (1)
{
delay_ms(200);
cdcdf_acm_write((void*)hello, 11);
}
}
does!
My hypothesis is that cdcdf_acm_write() has a problem somewhere in the USB stack that cannot read data straight from flash, which seems like a very unexpected pitfall, especially as outputting a string constant is probably the first thing one does while implementing the communication functionality!

asynchronous serial port communication in windows in c

I am getting an error when I try to run a c file which does some basic writes to a serial port. I am trying to run it asynchronously because the writes sometimes take a long time to transfer. My original version had it running synchronously with WriteFile() commands which worked fine. I am new to using OVERLAPPED and would appreciate and input concerning it.
The error I am getting is:
Debug Assertion Failed!
<path to dbgheap.c>
Line: 1317
Expression: _CrtIsValidHeapPointer(pUserData)
when the second write function is called.
In main:
{
//initialized port (with overlapped), DBC, and timeouts
result = write_port(outPortHandle, 128);
result = write_port(outPortHandle, 131);
}
static void CALLBACK write_compl(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) {
//write completed. check for errors? if so throw an exception maybe?
printf("write completed--and made it to callback function\n");
}
int write_port(HANDLE hComm,BYTE* lpBuf) {
OVERLAPPED osWrite = {0};
// Create this write operation's OVERLAPPED structure's hEvent.
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osWrite.hEvent == NULL)
// error creating overlapped event handle
return 0;
// Issue write.
if (!WriteFileEx(hComm, &lpBuf, 1, &osWrite, &write_compl )) {
if (GetLastError() != ERROR_IO_PENDING) {
// WriteFile failed, but isn't delayed. Report error and abort.
printf("last error: %ld",GetLastError());
return 0; //failed, return false;
}
else {
// Write is pending.
WaitForSingleObjectEx(osWrite.hEvent, 50, TRUE); //50 ms timeout
return -1; //pending
}
}
else {
return 1; //finished
}
}
That was not the full code, sorry. I was using an array of BYTEs as well, not constants. But system("pause")'s were causing my debug assertion failed errors, and after carefully looking through my code, when the WriteFileEx() was successful, it was never setting an alert/timeout on the event in the overlapped structure, so the callback function would never get called. I fixed these problems though.
I just need help with the handling/accessing a single BYTE in a structure which is allocated when a ReadFileEx() function is called (for storing the BYTE that is read so it can be handled). I need to know how to access that BYTE storage using an offset and make the overlapped structure null. Would making the overlapped structure null be as simple as setting the handle in it to INVALID_HANDLE_VALUE?
I think you have a couple of issues:
You are passing an integer as a pointer (your compiler should warn against this or preferably refuse to compile the code):
result = write_port(outPortHandle, 128);
Compare this to the definition of write_port:
int write_port(HANDLE hComm,BYTE* lpBuf) {
The above statements doesn't match. Later on you then pass a pointer to the lpBuf pointer to the WriteFileEx function by taking the address of the BYTE* -> "&lpBuf". This will not result in what you think it will do.
Even if you fix this, you will still have potential lifetime issues whenever the write is successfully queued but won't complete within the 50 ms timeout.
When using overlapped I/O, you need to make sure that the read/write buffer and the overlapped structure remain valid until the I/O is completed, cancelled or the associated device is closed. In your code above you use a pointer to an OVERLAPPED struct that lives on the stack in your call to WriteFileEx. If WriteFileEx does not complete within 50 ms, the pending I/O will have a reference to a non-existing OVERLAPPED struct and you will (hopefully) have an access violation (or worse, silently corrupted stack data somewhere in your app).
The canonical way of handling these lifetime issues (if performance is not a big issue), is to use a custom struct that includes an OVERLAPPED struct and some storage for the data to be read/written. Allocate the struct when posting the write and deallocate the struct from the I/O completion routine. Pass the address of the included OVERLAPPED struct to WriteFileEx, and use e.g. offsetof to get the address to the custom struct from the OVERLAPPED address in the completion routine.
Also note that WriteFileEx does not actually use the hEvent member, IIRC.
EDIT: Added code sample, please note:
I haven't actually tried to compile the code, there might be typos or other problems with the code.
It's not the most efficient way of sending data (allocating/deallocating a memory block for each byte that is sent). It should be easy to improve, though.
#include <stddef.h>
#include <assert.h>
#include <windows.h>
// ...
typedef struct _MYOVERLAPPED
{
OVERLAPPED ol;
BYTE buffer;
} MYOVERLAPPED, *LPMYOVERLAPPED;
// ...
static void CALLBACK write_compl(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
{
if (NULL == lpOverlapped)
{
assert(!"Should never happen");
return;
}
LPBYTE pOlAsBytes = (LPBYTE)lpOverlapped;
LPBYTE pMyOlAsBytes = pOlAsBytes - offsetof(MYOVERLAPPED, ol);
LPMYOVERLAPPED pMyOl = (LPMYOVERLAPPED)pOlAsBytes;
if ((ERROR_SUCCESS == dwErrorCode) &&
(sizeof(BYTE) == dwNumberOfBytesTransfered))
{
printf("written %uc\n", pMyOl->buffer);
}
else
{
// handle error
}
free(pMyOl);
}
int write_port(HANDLE hComm, BYTE byte) {
LPMYOVERLAPPED pMyOl = (LPMYOVERLAPPED)malloc(sizeof(MYOVERLAPPED));
ZeroMemory(pMyOl, sizeof(MYOVERLAPPED));
pMyOl->buffer = byte;
// Issue write.
if (!WriteFileEx(hComm, &pMyOl->buffer, sizeof(BYTE), pMyOl, &write_compl )) {
if (GetLastError() != ERROR_IO_PENDING) {
// WriteFile failed, but isn't delayed. Report error and abort.
free(pMyOl);
printf("last error: %ld",GetLastError());
return 0; //failed, return false;
}
else {
return -1; //pending
}
}
else {
free(pMyOl);
return 1; //finished
}
}
result = write_port(outPortHandle, 128);
result = write_port(outPortHandle, 131);
The lpBuf argument have to be pointers to buffers, not constants.
e.g.
char buffer;
buffer = 128;
result = write_port(outPortHandle, &buffer);
buffer = 131;
result = write_port(outPortHandle, &buffer);
What you really want to do is also pass a buffer length.
e.g.
char buffer[] = { 128, 131 };
result = write_port(outPortHandle, &buffer, sizeof(buffer));
int write_port(HANDLE hComm,BYTE* lpBuf, size_t length) {
...
// Issue write.
if (!WriteFileEx(hComm, &lpBuf, length, &osWrite, &write_compl )) {
...

Resources