Пустой указатель в моем коде SDL, вероятно, дает мне неправильный вывод.Как я могу отладить это? - PullRequest
0 голосов
/ 13 мая 2018

Я пытаюсь реструктурировать свой код для декодирования MJPEG, чтобы я мог реализовать его гетерогенным образом.Я начал с поиска сегментов кода, которые, по моему мнению, могли бы выиграть от параллельной обработки.Я получил однопоточный код процессора от этой ссылки.

Следующий код работает правильно . Обратите внимание, что я пропустил некоторые части кода, чтобы лучше представить его здесь .

//Original MCU blocks
MCU_main AllMCUs[nb_MCU_X * nb_MCU_Y];

int32_t MCU[64];


//All RGB blocks
RGB_struct AllRGBs[nb_MCU_X * nb_MCU_Y];

//Counter for the main MCUs
uint32_t x;

x=0;

///////--------Unpack-blocks for 3 color components

                    //process 8x8 blocks horizontally
                    for (index_X = 0; index_X < nb_MCU_X; index_X++) {
                        //process 8x8 blocks vertically
                        for (index_Y = 0; index_Y < nb_MCU_Y; index_Y++) {

                                AllMCUs[x].block_id=x;

                                component_index = component_order[0];

                                AllMCUs[x].MCU= MCU;

                            unpack_block(movie, &scan_desc,0, AllMCUs[x].MCU);


                            for (int i=0; i < 64; i++)
                         {
                             AllMCUs[x].MCU_Y[i]= AllMCUs[x].MCU[i];
                          }


                        unpack_block(movie, &scan_desc,1, AllMCUs[x].MCU);


                        for (int i=0; i < 64; i++)
                        {
                            AllMCUs[x].MCU_Cb[i]= AllMCUs[x].MCU[i];
                        }

                        unpack_block(movie, &scan_desc,2, AllMCUs[x].MCU);

                        for (int i=0; i < 64; i++)
                    {
                        AllMCUs[x].MCU_Cr[i]= AllMCUs[x].MCU[i];
                    }
                        x+= 1;

                        }
                    }


///////-----------IQZZ, IDCT, Upsampling and Color-conversion---------///////

uint32_t y=0;
x=0;

for (index_X = 0; index_X < nb_MCU_X; index_X++) {
   for (index_Y = 0; index_Y < nb_MCU_Y; index_Y++) {

            if(AllMCUs[x].block_id == y){
        //iqzz, idct and upsampling for Y       
        iqzz_block();
        idct();
        upsampler();

        //iqzz, idct and upsampling for Cb
        iqzz_block();
        idct();
        upsampler();

        //iqzz, idct and upsampling for Cr
        iqzz_block();
        idct();
        upsampler();

        AllRGBs[x].block_id= x;
        //color-conversion
        if(color && (SOF_section.n > 1)){
         YCbCr_to_ARGB(YCbCr_MCU, &AllRGBs[x].RGB_MCU, max_ss_h, max_ss_v);
        }
        else{
            to_NB(YCbCr_MCU, RGB_MCU, max_ss_h, max_ss_v);
        }

screen_cpyrect(index_Y * MCU_sy * max_ss_h, index_X * MCU_sx * max_ss_v, MCU_sy * max_ss_h, MCU_sx * max_ss_v, &AllRGBs[x].RGB_MCU);


x+=1;
y+=1;
            }
        }
    }

Правильный вывод выглядит следующим образом:

enter image description here

Моя структура для RGB_struct выглядит следующим образом:

typedef struct{
uint32_t block_id;
uint32_t *RGB_MCU
}RGB_struct;

Моя структура для MCU_main (хотя и не имеет непосредственного отношения к делу) такова:

typedef struct{
uint32_t block_id;
int32_t *MCU_original;
int32_t MCU_Cb[64], MCU_Cr[64], MCU_Y[64];
}MCU_main;

screen_cpyrect копирует каждый блок 8x8 на экране в соответствии со значениями смещения.Код для него следующий (такой же, как код из этой ссылки):

void screen_cpyrect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, void *ptr)
{
    void *dest_ptr;
    void *src_ptr;
    uint32_t line;
    uint32_t w_internal = w, h_internal = h;
    int w_length;

    SDL_LockSurface(screen);
    w_length = screen->pitch / (screen->format->BitsPerPixel / 8 );

#ifdef DEBUG
    if ((y) > screen->h) {
        printf("[%s] : block can't be copied, "
                "not in the screen (too low)\n", __func__);
        exit(1);
    }
    if ((x) > screen->w) {
        printf("[%s] : block can't be copied, "
                "not in the screen (right border)\n", __func__);
        exit(1);
    }
#endif
    if ((x+w) > screen->w) {
        w_internal = screen->w -x;
    }
    if ((y+h) > screen->h) {
        h_internal = screen->h -y;
    }
    for(line = 0; line < h_internal ; line++)
    {
        // Positionning src and dest pointers
        //  _ src : must be placed at the beginning of line "line"
        //  _ dest : must be placed at the beginning
        //          of the corresponding block :
        //(line offset + current line + position on the current line)
        // We assume that RGB is 4 bytes

        dest_ptr = (void*)((uint32_t *)(screen->pixels) +
                ((y+line)*w_length) + x);
        src_ptr = (void*)((uint32_t *)ptr + ((line * w)));
        memcpy(dest_ptr,src_ptr,w_internal * sizeof(uint32_t));
    }

    SDL_UnlockSurface(screen);
}

Я хочу, чтобы функция screen_cpyrect оставалась на процессоре.Однако в моем рабочем коде он связан с остальными функциями JPEG. Чтобы сделать мой код более параллельным, я попытался отделить его от других функций JPEG.

Следующий код НЕ выдает правильный вывод:

///////--------Unpack-blocks for 3 color components

//process 8x8 blocks horizontally
for (index_X = 0; index_X < nb_MCU_X; index_X++) {
    //process 8x8 blocks vertically
    for (index_Y = 0; index_Y < nb_MCU_Y; index_Y++) {

                        //For Y
                        unpack_block(movie, &scan_desc,0, AllMCUs[x].MCU);

                        //For Cb
                        unpack_block(movie, &scan_desc,1, AllMCUs[x].MCU);

                        //For Cr
                        unpack_block(movie, &scan_desc,2, AllMCUs[x].MCU);

                        x+= 1;

    }

}

///////-----------IQZZ, IDCT, Upsampling and Color-conversion---------///////

uint32_t y=0;
x=0;

for (index_X = 0; index_X < nb_MCU_X; index_X++) {
   for (index_Y = 0; index_Y < nb_MCU_Y; index_Y++) {

            if(AllMCUs[x].block_id == y){
        //iqzz, idct and upsampling for Y       
        iqzz_block();
        idct();
        upsampler();

        //iqzz, idct and upsampling for Cb
        iqzz_block();
        idct();
        upsampler();

        //iqzz, idct and upsampling for Cr
        iqzz_block();
        idct();
        upsampler();

        AllRGBs[x].block_id= x;
        //color-conversion
        if(color && (SOF_section.n > 1)){
         YCbCr_to_ARGB(YCbCr_MCU, &AllRGBs[x].RGB_MCU, max_ss_h, max_ss_v);
        }
        else{
            to_NB(YCbCr_MCU, RGB_MCU, max_ss_h, max_ss_v);
        }

x+=1;
y+=1;
            }
        }
    }

//COPYING ALL THE PROCESSED BLOCKS TO THE SCREEN SEPARATELY 
x=0;
for (index_X = 0; index_X < nb_MCU_X; index_X++) {
    for (index_Y = 0; index_Y < nb_MCU_Y; index_Y++) {
        screen_cpyrect(index_Y * MCU_sy * max_ss_h, index_X * MCU_sx * max_ss_v, MCU_sy * max_ss_h, MCU_sx * max_ss_v, &AllRGBs[x].RGB_MCU);
        x+=1;
}
}

if (screen_refresh() == 1) 
{
    end_of_file = 1;
}

Я получаю полностью искаженный вывод.Кадры обрабатываются, но отображаются неправильно.Неправильный вывод выглядит следующим образом:

enter image description here

Код для преобразования цвета выглядит следующим образом (скопировано с этой ссылки):

void YCbCr_to_ARGB(uint8_t *YCbCr_MCU[3], uint32_t *RGB_MCU, uint32_t nb_MCU_H, uint32_t nb_MCU_V)
{

    uint8_t *MCU_Y, *MCU_Cb, *MCU_Cr;
    int R, G, B;
    uint32_t ARGB;
    uint8_t index, i, j;

    MCU_Y = YCbCr_MCU[0];
    MCU_Cb = YCbCr_MCU[1];
    MCU_Cr = YCbCr_MCU[2];
    for (i = 0; i < 8 * nb_MCU_V; i++) {
        for (j = 0; j < 8 * nb_MCU_H; j++) {
            index = i * (8 * nb_MCU_H)  + j;
            R = (MCU_Cr[index] - 128) * 1.402f + MCU_Y[index];
            B = (MCU_Cb[index] - 128) * 1.7772f + MCU_Y[index];
            G = MCU_Y[index] - (MCU_Cb[index] - 128) * 0.34414f -
                (MCU_Cr[index] - 128) * 0.71414f;
            /* Saturate */
            if (R > 255)
                R = 255;
            if (R < 0)
                R = 0;
            if (G > 255)
                G = 255;
            if (G < 0)
                G = 0;
            if (B > 255)
                B = 255;
            if (B < 0)
                B = 0;
            ARGB = ((R & 0xFF) << 16) | ((G & 0xFF) << 8) | (B & 0xFF);
            // ARGB = 0xFF << 8;
            RGB_MCU[(i * (8 * nb_MCU_H) + j)] = ARGB;
        }
    }
}

Я не понимаю, почему мой модифицированный код для декодирования кадров не должен работать правильно.Я попытался отладить его различными способами, и я не нашел явных проблем в альтернативной реализации.Все значения массива AllRGBs хранятся правильно.Я распечатал значения, и они идентичны.

RGB before cpy_rect:0x7fff8f868bf8 RGB before cpy_rect:0x7fff8f868c08 RGB before cpy_rect:0x7fff8f868c18 RGB before cpy_rect:0x7fff8f868c28.......


RGB after cpy_rect:0x7fff8f868bf8 RGB after cpy_rect:0x7fff8f868c08 RGB after cpy_rect:0x7fff8f868c18 RGB after cpy_rect:0x7fff8f868c28  

Есть ли у вас какие-либо мысли о том, почему одна версия кода дает правильный вывод, а другая - нет?

EDIT:

Чтобы протестировать мой код, я написал код для отображения каждого блока 8x8, как только он будет скопирован на экран.Я заметил, что в моем правильном коде блоки копируются правильно.Однако в моем неправильном коде блоки 8x8 отображаются неправильно (как вы можете видеть на фотографиях, которые я прикрепил).

Почему это должно происходить, даже если значения RGB в обеих моих программах одинаковы?Как получается, что когда я копирую все блоки RGB на экране за один раз, я получаю неправильный вывод?

РЕДАКТИРОВАТЬ:

После тестирования кодаВ любом случае, я начинаю думать, что эта проблема возникает из-за указателя void.

Один из входных параметров screen_cpyrect является указателем void:

extern void screen_cpyrect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, void *ptr)

RGB_MCU используется в качестве аргумента функции вместо ptr.Однако ptr является указателем на все, тогда как RGB_MCU является указателем на тип uint32_t, как показано в этом объявлении:

typedef struct{
uint32_t block_id;
uint32_t *RGB_MCU
}RGB_struct;

Я прочитал в комментарии для this ответьте, что, если указатель void используется неправильно, это может привести к тому, что программа выдаст неправильный вывод или просто произойдет сбой.

Как я могу подтвердить, что проблема, с которой я столкнулся, связана с указателем void?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...