Adından da anlaşılacağı gibi, veri 64x32 piksel "fayans" içine paketlenmiştir.
Kod çözülmüş resmi uyumlu bir donanım yüzeyine yazarsanız, piksel formatını bilmeniz gerekmez.
En azından bazı video genişlikleri için, biçimi (Luma sadece şimdilik) ters mühendislik yaptım. Ancak (henüz) chroma örneklerinin nasıl yerleştirildiğini bilmiyorum ve aşağıdaki kod hala buggy.
void CopyOmxPicture(decoder_t *p_dec, picture_t *p_pic,
OMX_BUFFERHEADERTYPE *p_header, int i_slice_height)
{
decoder_sys_t *p_sys = p_dec->p_sys;
int i_src_stride;
int i_plane, i_width, i_line;
uint8_t *p_dst, *p_src, *p_dst2;
i_src_stride = p_sys->out.i_frame_stride;
p_src = p_header->pBuffer + p_header->nOffset;
if(p_dec->p_sys->out.definition.format.video.eColorFormat == QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka)
{
uint8_t *to = p_pic->p[0].p_pixels;
int w = p_pic->p[0].i_visible_pitch;
int h = p_pic->p[0].i_visible_lines;
int pitch = p_pic->p[0].i_pitch;
msg_Dbg(p_dec, "stride %d pitch %d w %d h %d", i_src_stride, pitch, w, h);
//copy luma plane
const int tsz = 64*32;
int wtiles = (w + 63)/64; // number of tiles in horizontal direction
int htiles = (h + 31)/32; // number of tiles in vertical direction
int tile = 0; // FIXME : order differs for other streams
int tiles_max = 2 * wtiles;
uint8_t order[tiles_max];
order[0] = 0;
order[1] = 1;
uint8_t done[tiles_max];
memset(done, 0, tiles_max);
done[0] = done[1] = 1;
int j = 2 + 4;
for (int i = 2; i < tiles_max;) {
while(done[j]) { j++; j%=tiles_max; }
done[j] = 1;
order[i++] = j++; j%= tiles_max;
while(done[j]) { j++; j%=tiles_max; }
done[j] = 1;
order[i++] = j++; j%= tiles_max;
if (j == 0)
continue;
if (i == tiles_max)
break;
while(done[j]) { j++; j%=tiles_max; }
done[j] = 1;
order[i++] = j++; j%= tiles_max;
while(done[j]) { j++; j%=tiles_max; }
done[j] = 1;
order[i++] = j++;
j += 4;
j%= tiles_max;
}
#if 0
static const uint8_t order[] = { 0, 1, 6, 7, 2, 3, 4, 5 };
static const uint8_t order[] = { 0, 1,
6, 7, 8, 9,
14, 15, 16, 17,
22, 23, 24, 25,
2, 3, 4, 5 ,
10, 11, 12, 13,
18, 19, 20, 21,
26, 27,
};
#endif
i_src_stride += 127; i_src_stride &= ~127;
//int width_align = tsz * (wtiles & 1); // width is aligned on 128 pixels
int width_align = i_src_stride - ((wtiles + 1) & ~1) * 64;
int soff = 0;
for (int i = 0; i < htiles; i++) { // top to bottom
int lines = 32;
if ((i == htiles - 1) && (h & 31))
lines = h & 31;
for (int j = 0; j < wtiles; j++) { // left to right
//copy one tile
int tile_pitch = 64;
if ((j == wtiles-1) && (w & 63))
tile_pitch = w & 63;
int doff = pitch * i * 32 + j * 64;
for (int l = 0; l < lines; l++) {
memcpy(&to[doff + l * pitch],
&p_src[soff + 64 * 32 * order[tile % tiles_max] + l * 64],
tile_pitch);
}
if ((++tile % tiles_max) == 0) {
soff += tiles_max * 64 * 32;
}
}
p_src += width_align;
}
// black out chroma
for (int i = 1; i < p_pic->i_planes; i++)
memset(p_pic->p[i].p_pixels, 0x80,
p_pic->p[i].i_pitch * p_pic->p[i].i_visible_lines);
#if 1 //dump
char mask[32];
static int x = 0;
sprintf(mask, "/sdcard/yuv/out%dx%dxp%d-%.3d.yuv", w, h, pitch, ++x);
if ((x & 15) == 0) {
FILE *f = fopen(mask, "w");
if ((f = fopen(mask, "w"))) {
#if 1
//int w = (p_pic->format.i_width + 127) & ~127;
//int h = (p_pic->format.i_height + 31) & ~31;
//size_t s = (w * h + 8191) & ~8191;
size_t s = p_header->nFilledLen;
fwrite(p_src, s, 1, f);
#else
fwrite(to, pitch*h*3/2, 1, f);
#endif
fclose(f);
}
}
#endif
}
}
cevabınızı düzenlemek ve okunabilir – kleopatra
@Anatoliy yapmak için kod biçimlendirmek lütfen .. – Denbian
Bu fonksiyon arabası orada kuyu düzenlemek için teşekkürler olduğunu. 720p kodunu çözüyorum ve uv karolarını birleştiren son döngüde çöküyor (line '_v [ichroma] = _src_vu [_interlace ++]; crashes). Bu arada, aralar iç içe geçmiyor, taramalı değil, yanlış ifade sadece kafa karıştırıcı. – Pavel