Anybody also noticed that Windows 11 multithreaded font usage causes a heap corruption in GDI? - multithreading

we have multiple printing applications that draw text into (an enhmetafile) GDI. When these painting actions (in short something like CreateFont(), SelectFont(), DrawText(), GetObject(), ... DeselectFont(), DeleteFont()) are done in threads, the application crashes very soon in DeleteObject() of a font handle. If the threads are synchronized, it does not happen. Under Windows 10 there's is no problem at all.
Reproduction by some simple code is not trivial, and our code is a little complex querying the LOGFONT, querying current object, ... to lay out the page to paint into (including wordbreak etc), and a simple multithreaded sample does not show this behaviour. It must be an unfortunate combination of the font APIs (or a combination with other GDI object APIs).
Trace of the crash is always in the same place, a corrupted heap caused by the DeleteObject API:
ntdll.dll!_RtlReportCriticalFailure#12() Unknown
ntdll.dll!_RtlpReportHeapFailure#4() Unknown
ntdll.dll!_RtlpHpHeapHandleError#12() Unknown
ntdll.dll!_RtlpLogHeapFailure#24() Unknown
ntdll.dll!_RtlpFreeHeapInternal#20() Unknown
ntdll.dll!RtlFreeHeap() Unknown
gdi32full.dll!_vFreeCFONTCrit#4() Unknown
gdi32full.dll!_vDeleteLOCALFONT#4() Unknown
gdi32.dll!_InternalDeleteObject#4() Unknown
gdi32.dll!_DeleteObject#4() Unknown
I do write it here in the hope of finding someone who has the same problem - or to be found by someone looking for others (like me here) ;)

OK, the culprit for our case of printing in a metafile DC has been found: the APIs GetTextExtentPoint() and its alias GetTextExtentPoint32() are not threadsafe in Windows 11 and do corrupt the GDI heap if GDI text operations are used by multiple threads.
More findings:
DC is a metafile DC:
heap becomes corrupted if `GetTextExtentPoint()´ is being used
everything works without this API
DC is a Window DC:
the code always hangs in an endless loop in ExtTextOut() or GetTextExtentPoint() (if opted in) in the application's painting loop. BTW: Even in Windows 10...! Not a deadlock, but full processor load (one at least one of the CPUs, so there's some kind of synchronization)
The code is attached, you may play around with the macros SHOW_ERROR and USE_METAFILE...:
#include "stdafx.h"
#include <windows.h>
#include <windowsx.h>
#include <process.h>
#include <assert.h>
#define SHOW_ERROR 1
#define USE_METAFILE 0
#define sizeofTSTR(b) (sizeof(b)/sizeof(TCHAR))
const int THREADCOUNT = 20;
struct scThreadData
{
public:
volatile LONG* _pnFinished;
TCHAR _szFilename[MAX_PATH];
DWORD _dwFileSize;
};
void _cdecl g_ThreadFunction(void* pParams)
{
scThreadData* pThreadData = reinterpret_cast<scThreadData*>(pParams);
PRINTDLG pd = {0};
HDC hDC = NULL;
::Sleep(rand() % 1000);
printf("start %d\n", ::GetCurrentThreadId());
#if USE_METAFILE
pd.lStructSize = sizeof(pd);
pd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
::PrintDlg(&pd);
RECT rcPage = {0,0,10000,10000};
hDC = ::CreateEnhMetaFile(pd.hDC, pThreadData->_szFilename, &rcPage, _T("Hallo"));
#else
hDC = ::GetDC(NULL);
#endif
for (int i = 0; i < 20000; ++i)
{
HFONT newFont = ::CreateFont(-100, 0, 0, 0, 0, 0, 0, 0, DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, 0, L"Arial");
HFONT oldFont = SelectFont(hDC, newFont);
::ExtTextOut(hDC, 0, 0, 0, NULL, _T("x"), 1, NULL);
#if SHOW_ERROR
SIZE sz = {};
::GetTextExtentPoint(hDC, L"Hallo", 5, &sz); // <<-- causes GDI heap to be corrupted
#endif
SelectFont(hDC, oldFont);
::DeleteFont(newFont);
}
#if USE_METAFILE
::DeleteEnhMetaFile(::CloseEnhMetaFile(hDC));
::DeleteDC(pd.hDC);
#else
::DeleteDC(hDC);
#endif
::DeleteFile(pThreadData->_szFilename);
printf("end %d\n", ::GetCurrentThreadId());
// done
::InterlockedIncrement(pThreadData->_pnFinished);
}
int _tmain(int argc, _TCHAR* argv[])
{
volatile LONG nFinished(0);
scThreadData TD[THREADCOUNT];
TCHAR szUserName[30];
TCHAR szComputerName[30];
DWORD dwLen;
dwLen = sizeofTSTR(szUserName);
::GetUserName(szUserName,&dwLen);
dwLen = sizeofTSTR(szComputerName);
::GetComputerName(szComputerName,&dwLen);
for (int nThread = 0; nThread < THREADCOUNT; ++nThread)
{
TD[nThread]._pnFinished = &nFinished;
_stprintf_s(TD[nThread]._szFilename,MAX_PATH,_T("test-%s-%d.emf"),szUserName,nThread);
_beginthread(g_ThreadFunction,10000,(void*)&TD[nThread]);
::Sleep(200);
}
Sleep(1000);
while (nFinished < THREADCOUNT)
{
::Sleep(100);
}
return 0;
}

Related

Qt C++ Displaying images outside the GUI thread (Boost thread)

I am developing a C++ library realizing its interface by means of Qt, using VS2015. On the library side, 3 boost threads continously load images from 3 folders. I am trying to display these images in 3 different QLabel (or equivalent QWidgets), so the thread body consists of this functionality,
in particular by exploiting the setPixmap method. Although the call to the function is protected by a boost mutex, I got exceptions probably due to threads synchronization. Looking for a solution, I already awared that the QPixmap widget is not "thread-safe" (non-reentrant). I also tried to use QGraphicsView but it in turn relies on QPixmap, thus I came across the same problem.
So my question is: does an alternative to QPixmap exist to display images in Qt in a thread-safe
manner?
I would recommend to do not multi-threading in GUI programming. Although, Qt provides multi-threading support in general, IMHO, the widgets are not well-prepared for this.
Thus, to achieve image loaders which run concurrently in separate threads I would suggest the following concept:
Each threaded image loader feeds a private buffer. The GUI inspects from time to time (using QTimer) these buffers and updates its QPixmap. As access to buffers should be possible from the resp. image loader thread as well as the GUI thread they have to be mutex guarded, of course.
My sample code testLoadImageMT.cc:
#include <atomic>
#include <chrono>
#include <mutex>
#include <thread>
#include <QtWidgets>
// manually added types (normally provided by glib)
typedef unsigned guint;
typedef unsigned char guint8;
// the fluffy-cat image sample
struct Image {
guint width;
guint height;
guint bytes_per_pixel; /* 3:RGB, 4:RGBA */
guint8 pixel_data[1];
};
extern "C" const Image fluffyCat;
class ImageLoader {
private:
const Image &_img;
std::atomic<bool> _exit;
std::mutex _lock;
QImage _qImg;
std::thread _thread;
public: // main thread API
ImageLoader(const Image &img = fluffyCat):
_img(img),
_qImg(img.width, img.height, QImage::Format_RGB888),
_exit(false), _thread(&ImageLoader::loadImage, std::ref(*this))
{ }
~ImageLoader()
{
_exit = true;
_thread.join();
}
ImageLoader(const ImageLoader&) = delete;
void applyImage(QLabel &qLblImg)
{
std::lock_guard<std::mutex> lock(_lock);
qLblImg.setPixmap(QPixmap::fromImage(_qImg));
}
private: // thread private
void loadImage()
{
for (;;) {
{ std::lock_guard<std::mutex> lock(_lock);
_qImg.fill(0);
}
size_t i = 0;
for (int y = 0; y < (int)_img.height; ++y) {
for (int x = 0; x < (int)_img.width; ++x) {
const quint32 value
= _img.pixel_data[i + 2]
| (_img.pixel_data[i + 1] << 8)
| (_img.pixel_data[i + 0] << 16)
| (0xff << 24);
i += _img.bytes_per_pixel;
{ std::lock_guard<std::mutex> lock(_lock);
_qImg.setPixel(x, y, value);
}
if (_exit) return; // important: make thread co-operative
}
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // slow down CPU cooler
}
}
}
};
int main(int argc, char **argv)
{
// settings:
enum { N = 3 }; // number of images loaded/displayed
enum { Interval = 50 }; // update rate for GUI 50 ms -> 20 Hz (round about)
// build appl.
qDebug() << "Qt Version: " << QT_VERSION_STR;
QApplication app(argc, argv);
// build GUI
QWidget qMainWin;
QVBoxLayout qVBox;
QLabel *pQLblImgs[N];
for (int i = 0; i < N; ++i) {
qVBox.addWidget(
new QLabel(QString::fromUtf8("Image %1").arg(i + 1)));
qVBox.addWidget(
pQLblImgs[i] = new QLabel());
}
qMainWin.setLayout(&qVBox);
qMainWin.show();
// build image loaders
ImageLoader imgLoader[N];
// install timer
QTimer qTimer;
qTimer.setInterval(Interval); // ms
QObject::connect(&qTimer, &QTimer::timeout,
[&imgLoader, &pQLblImgs]() {
for (int i = 0; i < N; ++i) {
imgLoader[i].applyImage(*pQLblImgs[i]);
}
});
qTimer.start();
// exec. application
return app.exec();
}
Sorry, I used std::thread instead of boost::thread as I've no experience with the latter, nor a working installation. I believe (hope) the differences will be marginal. QThread would have been the "Qt native" alternative but again – no experiences.
To keep things simple, I just copied data out of a linked binary image (instead of loading one from file or from anywhere else). Hence, a second file has to be compiled and linked to make this an MCVE – fluffyCat.cc:
/* GIMP RGB C-Source image dump (fluffyCat.cc) */
// manually added types (normally provided by glib)
typedef unsigned guint;
typedef unsigned char guint8;
extern "C" const struct {
guint width;
guint height;
guint bytes_per_pixel; /* 3:RGB, 4:RGBA */
guint8 pixel_data[16 * 16 * 3 + 1];
} fluffyCat = {
16, 16, 3,
"x\211s\215\232\200gw`fx`at[cx^cw^fu\\itZerWn|ap~cv\204jnzedq^fr^kzfhv^Ra"
"GRbMWdR\\jXer^qw_\311\256\226\271\253\235\275\264\252\315\277\260\304\255"
"\231u~i\213\225\207l{fly`jx\\^nRlz_z\206nlx`t~i\221\211s\372\276\243\375"
"\336\275\376\352\340\356\312\301\235\216\212judgwcl~f\212\226u}\206h\212"
"\224q\231\237z\232\236{\216\225v\225\230\200\306\274\244\376\360\327\376"
"\361\331\376\360\341\326\275\272\253\240\244{\203p\202\220xp~e{\204^\222"
"\230n\212\217g\240\242{\234\236z\214\222r\270\271\247\360\353\340\376\370"
"\336\376\363\334\375\357\336\310\254\262\232\223\234\\gRfrX\204\220z\212"
"\225g\225\232j\254\255\177\252\250{\225\226u\304\302\265\374\365\351\376"
"\375\366\376\367\341\376\361\320\374\346\324\306\241\242\237\232\235n{fj"
"xckyfu~fUX#VZCfnT\231\231\207\374\374\371\377\372\354\376\376\374\376\376"
"\372\376\362\332\375\340\301\341\300\264\260\253\262jvdbq\\XkVJTDNTCCG8O"
"TE\322\321\313\377\377\375\376\376\373\376\377\376\376\376\375\376\374\362"
"\376\360\342\344\311\306\250\244\254R_PL^HXkT<#2OP#`dP\217\220\177\374\374"
"\370\377\377\374\376\375\371\377\377\376\376\374\360\377\367\336\376\350"
"\316\342\303\274\246\236\245jtbXdQTdNQYGU\\KchV\317\315\302\377\376\372\377"
"\376\367\376\373\360\377\376\367\376\366\337\376\355\312\374\331\271\323"
"\263\251\216\214\214\\hTP^HL\\FR[LMXI^dW\355\352\342\376\375\366\377\374"
"\360\376\374\361\376\374\361\376\356\321\374\331\264\374\330\266\330\270"
"\260\200||Y`SLVE>K9BJ<CN?VYP\347\330\322\376\366\345\376\363\330\376\367"
"\337\377\372\350\374\342\314\326\243\210\375\350\314\352\317\304shc^`TV`"
"RVbT>B4IS?PTD\244\232\216\374\355\320\376\354\311\376\351\306\376\362\332"
"\374\344\321\267\206u\375\362\337\326\274\272\\POMNBT]LNZH:<*<A*TV>OI;\242"
"\222\207\340\304\243\375\335\262\372\336\272\376\361\334\320\241\212\374"
"\352\322\266\233\237c\\WFH;MR>\\`F~xP\220\214[pqE\211\202\\g]=\230\214`\313"
"\266\207\344\303\240\362\336\274\323\257\201\333\304\240\305\252\204\254"
"\232p\216\206\\\206\203U\232\224b\234\244b\246\257m\220\232`\224\227h~\202"
"W\206\213]\204\210W\227\227i|\177RvzNlsGrtJwtLz}N{\204RlxF",
};
I compiled and tested in VS2013, with Qt 5.9.2 on Windows 10 (64 bit). This is how it looks:
I solved using signal/slot: the "non-GUI" thread emits a signal instead of displaying the images and the called slot paints the QLabel inside the GUI thread!

multiple thread in CMSIS RTOS - STM32 nucleo L053R8

Today I developing RTOS (CMSIS RTOS) for kit STM32 nucleo L053R8. I have issue relate to multiple task.
I create 4 task(task_1, task_2, task_3, task_4), however only 3 task run.
This is part of my code:
#include "main.h"
#include "stm32l0xx_hal.h"
#include "cmsis_os.h"
osMutexId stdio_mutex;
osMutexDef(stdio_mutex);
int main(void){
.....
stdio_mutex = osMutexCreate(osMutex(stdio_mutex));
osThreadDef(defaultTask_1, StartDefaultTask_1, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask_1), NULL);
osThreadDef(defaultTask_2, StartDefaultTask_2, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask_2), NULL);
osThreadDef(defaultTask_3, StartDefaultTask_3, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask_3), NULL);
osThreadDef(defaultTask_4, StartDefaultTask_4, osPriorityNormal, 0, 600);
defaultTaskHandle = osThreadCreate(osThread(defaultTask_4), NULL);
}
void StartDefaultTask_1(void const * argument){
for(;;){
osMutexWait(stdio_mutex, osWaitForever);
printf("%s\n\r", __func__);
osMutexRelease(stdio_mutex);
osDelay(1000);
}
}
void StartDefaultTask_2(void const * argument){
for(;;){
osMutexWait(stdio_mutex, osWaitForever);
printf("%s\n\r", __func__);
osMutexRelease(stdio_mutex);
osDelay(1000);
}
}
void StartDefaultTask_3(void const * argument){
for(;;){
osMutexWait(stdio_mutex, osWaitForever);
printf("%s\n\r", __func__);
osMutexRelease(stdio_mutex);
osDelay(1000);
}
}
void StartDefaultTask_4(void const * argument){
for(;;){
osMutexWait(stdio_mutex, osWaitForever);
printf("%s\n\r", __func__);
osMutexRelease(stdio_mutex);
osDelay(1000);
}
}
this is reslut in console (uart):
when I change stack size for task 4 from 600 -> 128 as below:
osThreadDef(defaultTask_4, StartDefaultTask_4, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask_4), NULL);
then don't have any task run.
Actualy I want make many thread for my application, however this issue cause difficult to implement.
Could you let me know root cause of prblem? and how to resolve it.
Thank you advance!!
There is no common easy method of the stack calculation. It depends on many factors.
I would suggest to avoid stack greedy functions like printf scanf etc. Write your own ones, not as "smart" and universal but less resources greedy.
Avoid large local variables. Be very careful when you allocate the memory
As your Suggestions, I checked by debug and see root cause is heap size is small.
I resolve by 2 method
increase heap size: #define configTOTAL_HEAP_SIZE ((size_t)5120)
decrease stack size: #define configMINIMAL_STACK_SIZE ((uint16_t)64)
osThreadDef(defaultTask_6, StartDefaultTask_6, osPriorityNormal, 0, 64);
Do you know how to determine max of heap size? Please let me known.
Thank you so much

The time consume is not normal in multi-thread in Windows

The time consume is not normal in multi-thread in Windows. Our device has 5 nozzles, the process is:
The nozzles pick chips up at the same time, so I use the 5 threads do it
Move the nozzles to another place
Put the chips
It's smooth at normal time, but sometimes it has a short stop before moving to another place (we can see it obviously). Picking chips takes about 80 milliseconds at normal time, and sometimes it becomes 130 milliseconds. I write a simple code to test it:
#include "stdafx.h"
#include <WINDOWS.H>
#include <PROCESS.H>
#include <iostream>
#include <Mmsystem.h>
#pragma comment(lib, "winmm.lib")
using namespace std;
static TIMECAPS l_timecaps;
UINT WINAPI MainThread(LPVOID lParam /* = NULL */);
UINT WINAPI TestThread(LPVOID lParam /* = NULL */);
void MainProcess();
int _tmain(int argc, _TCHAR* argv[])
{
//set current process priority as real time
SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
//use more accurate time
timeGetDevCaps(&l_timecaps, sizeof(l_timecaps));
timeBeginPeriod(l_timecaps.wPeriodMin);
UINT uiThreadId = 0;
HANDLE hEvents = (HANDLE) _beginthreadex(NULL, 0, MainThread, NULL, 0, &uiThreadId);
SetThreadPriority(hEvents, THREAD_PRIORITY_TIME_CRITICAL);
WaitForSingleObject(hEvents, INFINITE);
cerr << endl << "Press Enter to exit." << endl;
while (cin.get() != '\n');
timeEndPeriod(l_timecaps.wPeriodMin);
return 0;
}
UINT WINAPI MainThread(LPVOID lParam /* = NULL */)
{
int i = 0;
while (i < 100)
{
MainProcess();
i++;
}
return 0;
}
void MainProcess()
{
const int THREAD_NUMBER = 5;
static HANDLE hEvents[THREAD_NUMBER];
for (int i = 0; i < THREAD_NUMBER; ++i)
hEvents[i] = NULL;
//log time with more accurate time
LARGE_INTEGER liPerfFreq={0};
LARGE_INTEGER liBeginRunTime = {0};
long lBeginRunTime = 0;
QueryPerformanceFrequency(&liPerfFreq);
QueryPerformanceCounter(&liBeginRunTime);
lBeginRunTime = liBeginRunTime.QuadPart * 1000 / liPerfFreq.QuadPart;
for (int i = 0; i < THREAD_NUMBER; ++i)
{
UINT uiThreadId = 0;
hEvents[i] = (HANDLE) _beginthreadex(NULL, 0, TestThread, NULL, 0, &uiThreadId);
SetThreadPriority(hEvents[i], THREAD_PRIORITY_TIME_CRITICAL);
//assign to cpu
SetThreadAffinityMask(hEvents[i], 0x00000001 + i);
}
//wait all threads finished
WaitForMultipleObjects(THREAD_NUMBER, hEvents, TRUE, INFINITE);
LARGE_INTEGER liEndRunTime = {0};
long lEndRunTime = 0;
QueryPerformanceCounter(&liEndRunTime);
lEndRunTime = liEndRunTime.QuadPart * 1000 / liPerfFreq.QuadPart;
cout << "time: " << lEndRunTime - lBeginRunTime << endl;
}
UINT WINAPI TestThread(LPVOID lParam /* = NULL */)
{
//do nothing
return 0;
}
The output result time is 2,3 or 4 millisecond, but sometimes it becomes 57 or 62 millisecond. It's bad for our device when running, the device becomes slow.
Your test threads do nothing. All the time is spent creating and shutting down the thread. Overheads in the kernel object manager and scheduler will dominate. Perhaps some of the threads are having to wait on other threads holding (via API calls) kernel locks and thus seeing delays.
And of course those inner threads could be completing before the call to set their priority completes: to set this you really need to start the thread suspended and then start it.
Because you are measuring nothing, all you have are overheads which will depend on what else is going on.
Also remember, while you have names like THREAD_PRIORITY_TIME_CRITICAL Windows is not a real-time OS.

ffmpeg/libavcodec memory management

The libavcodec documentation is not very specific about when to free allocated data and how to free it. After reading through documentation and examples, I've put together the sample program below. There are some specific questions inlined in the source but my general question is, am I freeing all memory properly in the code below? I realize the program below doesn't do any cleanup after errors -- the focus is on final cleanup.
The testfile() function is the one in question.
extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
}
#include <cstdio>
using namespace std;
void AVFAIL (int code, const char *what) {
char msg[500];
av_strerror(code, msg, sizeof(msg));
fprintf(stderr, "failed: %s\nerror: %s\n", what, msg);
exit(2);
}
#define AVCHECK(f) do { int e = (f); if (e < 0) AVFAIL(e, #f); } while (0)
#define AVCHECKPTR(p,f) do { p = (f); if (!p) AVFAIL(AVERROR_UNKNOWN, #f); } while (0)
void testfile (const char *filename) {
AVFormatContext *format;
unsigned streamIndex;
AVStream *stream = NULL;
AVCodec *codec;
SwsContext *sws;
AVPacket packet;
AVFrame *rawframe;
AVFrame *rgbframe;
unsigned char *rgbdata;
av_register_all();
// load file header
AVCHECK(av_open_input_file(&format, filename, NULL, 0, NULL));
AVCHECK(av_find_stream_info(format));
// find video stream
for (streamIndex = 0; streamIndex < format->nb_streams && !stream; ++ streamIndex)
if (format->streams[streamIndex]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
stream = format->streams[streamIndex];
if (!stream) {
fprintf(stderr, "no video stream\n");
exit(2);
}
// initialize codec
AVCHECKPTR(codec, avcodec_find_decoder(stream->codec->codec_id));
AVCHECK(avcodec_open(stream->codec, codec));
int width = stream->codec->width;
int height = stream->codec->height;
// initialize frame buffers
int rgbbytes = avpicture_get_size(PIX_FMT_RGB24, width, height);
AVCHECKPTR(rawframe, avcodec_alloc_frame());
AVCHECKPTR(rgbframe, avcodec_alloc_frame());
AVCHECKPTR(rgbdata, (unsigned char *)av_mallocz(rgbbytes));
AVCHECK(avpicture_fill((AVPicture *)rgbframe, rgbdata, PIX_FMT_RGB24, width, height));
// initialize sws (for conversion to rgb24)
AVCHECKPTR(sws, sws_getContext(width, height, stream->codec->pix_fmt, width, height, PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL));
// read all frames fromfile
while (av_read_frame(format, &packet) >= 0) {
int frameok = 0;
if (packet.stream_index == (int)streamIndex)
AVCHECK(avcodec_decode_video2(stream->codec, rawframe, &frameok, &packet));
av_free_packet(&packet); // Q: is this necessary or will next av_read_frame take care of it?
if (frameok) {
sws_scale(sws, rawframe->data, rawframe->linesize, 0, height, rgbframe->data, rgbframe->linesize);
// would process rgbframe here
}
// Q: is there anything i need to free here?
}
// CLEANUP: Q: am i missing anything / doing anything unnecessary?
av_free(sws); // Q: is av_free all i need here?
av_free_packet(&packet); // Q: is this necessary (av_read_frame has returned < 0)?
av_free(rgbframe);
av_free(rgbdata);
av_free(rawframe); // Q: i can just do this once at end, instead of in loop above, right?
avcodec_close(stream->codec); // Q: do i need av_free(codec)?
av_close_input_file(format); // Q: do i need av_free(format)?
}
int main (int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "usage: %s filename\n", argv[0]);
return 1;
}
testfile(argv[1]);
}
Specific questions:
Is there anything I need to free in the frame processing loop; or will libav take care of memory management there for me?
Is av_free the correct way to free an SwsContext?
The frame loop exits when av_read_frame returns < 0. In that case, do I still need to av_free_packet when it's done?
Do I need to call av_free_packet every time through the loop or will av_read_frame free/reuse the old AVPacket automatically?
I can just av_free the AVFrames at the end of the loop instead of reallocating them each time through, correct? It seems to be working fine, but I'd like to confirm that it's working because it's supposed to, rather than by luck.
Do I need to av_free(codec) the AVCodec or do anything else after avcodec_close on the AVCodecContext?
Do I need to av_free(format) the AVFormatContext or do anything else after av_close_input_file?
I also realize that some of these functions are deprecated in current versions of libav. For reasons that are not relevant here, I have to use them.
Those functions are not just deprecated, they've been removed some time ago. So you should really consider upgrading.
Anyway, as for your questions:
1) no, nothing more to free
2) no, use sws_freeContext()
3) no, if av_read_frame() returns an error then the packet does not contain any valid data
4) yes you have to free the packet after you're done with it and before next av_read_frame() call
5) yes, it's perfectly valid
6) no, the codec context itself is allocated by libavformat so av_close_input_file() is
responsible for freeing it. So nothing more for you to do.
7) no, av_close_input_file() frees the format context so there should be nothing more for you to do.

error: undefined reference to `sched_setaffinity' on windows xp

Basically the code below was intended for use on linux and maybe thats the reason I get the error because I'm using windows XP, but I figure that pthreads should work just as well on both machines. I'm using gcc as my compiler and I did link with -lpthread but I got the following error anyways.
|21|undefined reference to sched_setaffinity'|
|30|undefined reference tosched_setaffinity'|
If there is another method to setting the thread affinity using pthreads (on windows) let me know. I already know all about the windows.h thread affinity functions available but I want to keep things multiplatform. thanks.
#include <stdio.h>
#include <math.h>
#include <sched.h>
double waste_time(long n)
{
double res = 0;
long i = 0;
while(i <n * 200000)
{
i++;
res += sqrt (i);
}
return res;
}
int main(int argc, char **argv)
{
unsigned long mask = 1; /* processor 0 */
/* bind process to processor 0 */
if (sched_setaffinity(0, sizeof(mask), &mask) <0)//line 21
{
perror("sched_setaffinity");
}
/* waste some time so the work is visible with "top" */
printf ("result: %f\n", waste_time (2000));
mask = 2; /* process switches to processor 1 now */
if (sched_setaffinity(0, sizeof(mask), &mask) <0)//line 30
{
perror("sched_setaffinity");
}
/* waste some more time to see the processor switch */
printf ("result: %f\n", waste_time (2000));
}
sched_getaffinity() and sched_setaffinity() are strictly Linux-specific calls. Windows provides its own set of specific Win32 API calls that affect scheduling. See this answer for sample code for Windows.

Resources