PageRenderTime 31ms CodeModel.GetById 18ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms

/Show/Avc.cpp

http://github.com/mbebenita/Broadway
C++ | 173 lines | 141 code | 26 blank | 6 comment | 27 complexity | 865e7da4158236756067801497a64d20 MD5 | raw file
  1#include <stdio.h>
  2#include <stdlib.h>
  3#include <SDL/SDL.h>
  4
  5#include "Avc.h"
  6
  7#define WIDTH 640
  8#define HEIGHT 480
  9#define BPP 4
 10#define DEPTH 32
 11
 12char *readFile(const char* filename, int *size) {
 13    FILE *file = fopen(filename, "rb");
 14    if (!file) {
 15        fprintf(stderr, "Unable to open file %s\n", filename);
 16        return NULL;
 17    }
 18    fseek(file, 0, SEEK_END);
 19    unsigned long bufferSize = ftell(file) + 1;
 20    fseek(file, 0, SEEK_SET);
 21    char *buffer = (char *) malloc(bufferSize);
 22    if (!buffer) {
 23        fprintf(stderr, "Memory error!\n");
 24        fclose(file);
 25        return NULL;
 26    }
 27    fread((char *) buffer, bufferSize, 1, file);
 28    fclose(file);
 29    *size = (int) bufferSize;
 30    return buffer;
 31}
 32
 33uintptr_t my_malloc(void *userData, int32 size, int attribute) {
 34    return (uintptr_t) malloc(size);
 35}
 36
 37void my_free(void *userData, uintptr_t mem) {
 38    free((void *) mem);
 39}
 40
 41Avc::Avc(const char *filename) {
 42    decoder.AVCObject = NULL;
 43    decoder.CBAVC_Malloc = my_malloc;
 44    decoder.CBAVC_Free = my_free;
 45    decoder.debugEnable = true;
 46    buffer = (uint8*) readFile(filename, &buffer_size);
 47    screen = NULL;
 48}
 49
 50int
 51Avc::pollKeyPress() {
 52    SDL_Event event;
 53    int keypress = 0;
 54    while (SDL_PollEvent(&event)) {
 55        switch (event.type) {
 56        case SDL_QUIT:
 57            keypress = 1;
 58            break;
 59        case SDL_KEYDOWN:
 60            keypress = 1;
 61            break;
 62        }
 63    }
 64    return keypress;
 65}
 66
 67int Avc::Play() {
 68    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
 69        return 1;
 70    }
 71
 72//    if (!(screen = SDL_SetVideoMode(WIDTH, HEIGHT, DEPTH, SDL_HWSURFACE))) {
 73//        SDL_Quit();
 74//        return 1;
 75//    }
 76
 77    uint8 *nal_unit = NULL;
 78    stream = buffer;
 79    int nal_size = buffer_size;
 80    int nal_number = 0;
 81    while (true) {
 82        if (PVAVCAnnexBGetNALUnit(stream, &nal_unit, &nal_size) != AVCDEC_SUCCESS) {
 83            printf("PVAVCAnnexBGetNALUnit Failed\n");
 84            PVAVCCleanUpDecoder(&decoder);
 85            break;
 86        }
 87
 88        trace("+ NAL Unit %d\n", nal_number++);
 89        trace("| nal_size: %d\n", nal_size);
 90
 91        if (decodeNALUnit(nal_unit, nal_size) == 0) {
 92            break;
 93        }
 94
 95        // SDL_Delay(1000 / 50);
 96
 97        stream = nal_unit + nal_size;
 98        nal_size = buffer_size - (stream - buffer);
 99
100        if (pollKeyPress()) {
101            break;
102        }
103
104        // SDL_Delay(1000 / 50);
105    }
106
107    SDL_Quit();
108    return 0;
109}
110
111int
112Avc::decodeNALUnit(uint8 *nal_unit, int nal_size) {
113    int nal_type = 0;
114    int nal_ref_idc = 0;
115
116    PVAVCDecGetNALType(nal_unit, nal_size, &nal_type, &nal_ref_idc);
117
118    trace("| nal_type: %d\n", nal_type);
119    trace("| nal_ref_idc: %d\n", nal_ref_idc);
120
121    if (nal_type == AVC_NALTYPE_SPS) {
122        PVAVCDecSeqParamSet(&decoder, nal_unit, nal_size);
123    } else if (nal_type == AVC_NALTYPE_PPS) {
124        PVAVCDecPicParamSet(&decoder, nal_unit, nal_size);
125    } else if (nal_type == AVC_NALTYPE_SLICE || nal_type == AVC_NALTYPE_IDR) {
126        if (1) {
127            int ret = PVAVCDecodeSlice(&decoder, nal_unit, nal_size);
128
129            int indx;
130            int release;
131
132            AVCFrameIO output;
133            PVAVCDecGetOutput(&decoder, &indx, &release, &output);
134
135            if (!screen) {
136                screen = SDL_SetVideoMode(output.pitch, output.height, 32, SDL_HWSURFACE | SDL_RESIZABLE);
137            }
138
139            if (0) {
140                SDL_LockSurface(screen);
141                uint8 *luma = output.YCbCr[0];
142                uint8 *cb = output.YCbCr[1];
143                uint8 *cr = output.YCbCr[2];
144                uint32 *dst = (uint32*) screen->pixels;
145                int stride = output.pitch;
146                int strideChroma = output.pitch >> 1;
147                for (int y = 0; y < output.height; y++) {
148                    int lineOffLuma = y * stride;
149                    int lineOffChroma = (y >> 1) * strideChroma;
150                    for (int x = 0; x < output.pitch; x++) {
151                        int c = luma[lineOffLuma + x] - 16;
152                        int d = cb[lineOffChroma + (x >> 1)] - 128;
153                        int e = cr[lineOffChroma + (x >> 1)] - 128;
154
155                        int red = (298 * c + 409 * e + 128) >> 8;
156                        red = red < 0 ? 0 : (red > 255 ? 255 : red);
157                        int green = (298 * c - 100 * d - 208 * e + 128) >> 8;
158                        green = green < 0 ? 0 : (green > 255 ? 255 : green);
159                        int blue = (298 * c + 516 * d + 128) >> 8;
160                        blue = blue < 0 ? 0 : (blue > 255 ? 255 : blue);
161                        int alpha = 255;
162                        dst[lineOffLuma + x] = SDL_MapRGB(screen->format, red & 0xff, green & 0xff, blue & 0xff);
163                    }
164                }
165                SDL_UnlockSurface(screen);
166                SDL_Flip(screen);
167            }
168        }
169    } else {
170        printf("Missed %d\n", nal_type);
171    }
172    return 1;
173}