I made an encoder using WIC. then i tryied to use thread for the most time consuming part. which is
/*Encodes a bitmap source*/
hr = piBitmapFrame->WriteSource(
piBitmapSrc, /*bitmap source*/
rc /*area which need to be wrote*/
);
piBitmapSrc → WICBitmap
rc → WICRect, rectangle area to do the work
This is how i tryied.
HRESULT writeSrc(
IWICBitmapFrameEncode *piBitmapFrame,
IWICBitmap *piBitmapSrc,
WICRect *rc
)
{
/*Encodes a bitmap source*/
hr = piBitmapFrame->WriteSource(
piBitmapSrc, /*bitmap source*/
rc /*area which need to be wrote*/
);
return hr;
}
and then I call it like this
const int numberOfThreads = 4;
std::thread t[numberOfThreads];
int ht = (lHeight / numberOfThreads);
WICRect rc;
rc.X = 0;
rc.Height = ht;
rc.Width = lWidth;
rc.Y = 0;
t[0] = std::thread(writeSrc, piBitmapFrame, piBitmapSrc, &rc);
rc.Y += ht;
t[1] = std::thread(writeSrc, piBitmapFrame, piBitmapSrc, &rc);
rc.Y += ht;
t[2] = std::thread(writeSrc, piBitmapFrame, piBitmapSrc, &rc);
rc.Y += ht;
rc.Height = (lHeight - (3*ht));
t[3] = std::thread(writeSrc, piBitmapFrame, piBitmapSrc, &rc);
t[0].join();
t[1].join();
t[2].join();
t[3].join();
problem is, piBitmapFrame->WriteSource()
called 4 times but only 1 returns S_OK. other 3 returns following error codes
WINCODEC_ERR_STREAMWRITE
or
WINCODEC_ERR_CODECTOOMANYSCANLINES
why is that. and how could i correctly use threads to do that
You might want to look into threads in general more. Threads share global data and resources. In your example, you are sharing the piBitMapFrame and WICRect structures across all four threads.
Considering the WICRect structure, you're actually modifying the data within as you're dispatching threads. That data, once modified, will be visible to all running threads. All threads are referencing the single WICRect you've declared, and if they inspect the same variable twice - they might find it's different.
I'm not familiar with this library, but you should check if WriteSource is a thread-safe call. Does piBitmapFrame contain data that might be modified by a call to WriteSource? Think back to the WICRect example above, WriteSource probably wouldn't handle internal data changing mid-call well.
An Example:
This program tries to print to stdout in two threads of execution, without any synchronization regarding who is writing when. This won't crash, cout is thread-safe, but it won't produce the output you might expect. The output will be both threads interleaving characters in the stdout buffer.
#include <iostream>
#include <thread>
void say_hello(){
/* no locking to prevent stdout contention */
for ( int i = 0; i < 10; i++){
std::cout << "Hello from thread " << std::this_thread::get_id() << "!!!" << std::endl;
}
}
int main(){
int i;
// create our thread
std::thread ct1(say_hello);
// say hello ourselves
say_hello();
// wait for thread ct1 to finish execution.
ct1.join();
return i;
}
Example Output:
HHeelllloo ffrroomm tthhrreeaadd 00xx170fcf5fd78b000007!3!0!0
!!H!e
llHoe lflroo mf rtohmr etahdr e0axd1 00cx57df8f0f070b!0!0!7
30H0e!l!l!o
fHreolml ot hfrreoamd t0hxr1e0acd5 d08x070f0f!f!7!b
00H7e3l0l0o! !f!r
omH etlhlroe afdr o0mx 1t0hcr5eda8d0 000x!7!f!f
f7Hbe0l0l7o3 0f0r!o!m!
thHreelaldo 0fxr1o0mc 5tdh8r0e0a0d! !0!x
7fHfefl7lbo0 0f7r3o0m0 !t!h!r
eaHde l0lxo1 0fcr5odm8 0t0h0r!e!a!d
0Hxe7lflfof 7fbr0o0m7 3t0h0r!e!a!d
0Hxe1l0lco5 df8r0o0m0 !t!h!r
eaHde l0lxo7 fffrfo7mb 0t0h7r3e0a0d! !0!x
10Hce5ldl8o0 0f0r!o!m!
thHreelaldo 0fxr7ofmf ft7hbr0e0a7d3 000x!1!0!c
5dH8e0l0l0o! !f!r
omH etlhlroe afdr o0mx 7tfhfrfe7abd0 007x31000c!5!d!8
00H0e!l!l!o
from thread 0x7fff7b007300!!!