Går detta att göra effektivare? (C/C++)

Permalänk
Medlem

Går detta att göra effektivare? (C/C++)

Tjena!

Sitter här och skriver lite kod och har en bit kod som funkar men som kanske inte är så jätteeffektiv. Tycker det ser ganska fult ut, men jag kan inte komma på hur sjutton man skulle kunna fixa det. Tänkte höra om det är nån som är sugen på att klura lite tillsammans med mig.

Om ni inte har så bra koll på color spaces och sånt så försöker jag förklara så gott jag kan vad det är jag försöker göra

Programmet sparar JPG-filer från en inkommande videoström med libjpeg. Den inkommande datan är kodad i UYVY, och jag skriver den med "jpeg_write_raw_data" för att slippa en del onödiga beräkningar. UYVY är redan downsamplat till 4:2:2 så det funkar ju rätt bra att stoppa rätt in i jpeg-codecen.

Problemet är att libjpeg inte gärna tar den råa datan som den är (UYVYUYVYUYVY...osv), utan vill ha den i fina små block med 16 rader i taget. Datan ska där ligga i fina arrays, först en med alla Y, sen en med alla V, och sist med alla U. Det enda sättet jag lyckas mata libjpeg på detta sätt är med ett gäng mindre roliga for-loopar. Här kommer iaf den relevanta koden:

jpeg_start_compress(&cinfo, true); JSAMPROW yv[16],cb[16],cr[16]; JSAMPARRAY data[3]; data[0]=yv; data[1]=cb; data[2]=cr; for (int i=0; i<height; i+=16){ for (int y=0; y<16; y++){ JSAMPLE* ysamp = new JSAMPLE[width]; JSAMPLE* cbsamp = new JSAMPLE[width/2]; JSAMPLE* crsamp = new JSAMPLE[width/2]; yv[y]=ysamp; cb[y]=cbsamp; cr[y]=crsamp; for (int x = 0; x<width; x++){ ysamp[x]=*(imageData+(2*x)+1+((width)*2*(y+i))*(1+interlace)); if(x<width/2){ cbsamp[x]=*(imageData+(4*x)+((width)*2*(y+i))*(1+interlace)); crsamp[x]=*(imageData+(4*x)+2+((width)*2*(y+i))*(1+interlace)); } } } jpeg_write_raw_data(&cinfo, data, 16); for (int y=0; y<16; y++){ delete yv[y]; delete cb[y]; delete cr[y]; } } jpeg_finish_compress(&cinfo);

imageData är en pointer till den råa UYVY-datan som jag använder lite aritmetik på för att stoppa rätt värde i arrayerna.

Är det for-loopar som gäller i såna här tillfällen? Känns ju så segt att behöva gå igenom varje pixel såhär och klippa och klistra som tusan. Finns det inte något bra sätt att skapa arrayer snabbt genom att ta exempelvis varannat värde från en char* ?

Tacksam för all input jag kan få. Har grubblat halva dagen

Visa signatur

Core i7 7700K | Titan X (Pascal) | MSI 270I Gaming Pro Carbon | 32 GiB Corsair Vengeance LPX @3000MHz | Samsung 960 EVO 1TB

Permalänk
Medlem

Det finns en par olika sätt att hantera situationen.
sizeof(char) är ju 1, och att 1 byte är 8 bitar. Låt säga att du har en 64bits maskin så kan du ju potentiellt slänga in 8st chars i en long long.
Med lämpligt valda bit maskar kan du nu operera på mer data åt gången.

Ett annat alternativ är att använda SIMD instruktioner (MMX, SSE, etc) för att hantera ännu mer data. Det finns speciella instruktioner för att packa och packa upp data samt att blanda (shuffle) för att få till dina sepparata arrayer.

kika lite på google codesearch så bör du kunna hitta lite exempel, du är inte den första som löst "problemet"

Visa signatur

weeeee

Permalänk
Medlem

Ska ta och kika på det. Är lite newbie på sån lågnivåprogrammering, på universitetet var det java för hela slanten med fokus på objektdesignen. Borde läst mer riktig programmering Jaja, det får man ta igen på egen hand såhär när man är klar med pluggandet. Kul att lära sig.

Visa signatur

Core i7 7700K | Titan X (Pascal) | MSI 270I Gaming Pro Carbon | 32 GiB Corsair Vengeance LPX @3000MHz | Samsung 960 EVO 1TB

Permalänk
Medlem

Använd SIMD som sagt var, du bör dessutom inte andopa new/delete så ofta som du gör. Ett anrop bör räcka. Du verkar göra cachevänliga minnescesser, då där har du nog inte så mycket att hämta. Sedan gäller det ju att inte gissa, utan kolla vad som verkligen tar tid. Kolla vad kompilatorn genererat för assembler etc.

Visa signatur

void@qnet
teeworlds, stålverk80, evil schemer, c, c++
Languages shape the way we think, or don't.

Permalänk
Medlem

Har flyttat ut alla new och delete nu iaf så de görs en gång istället. Det blev lite bättre Borde jag sett själv XD

Visa signatur

Core i7 7700K | Titan X (Pascal) | MSI 270I Gaming Pro Carbon | 32 GiB Corsair Vengeance LPX @3000MHz | Samsung 960 EVO 1TB