/Show/Avc.cpp
C++ | 173 lines | 141 code | 26 blank | 6 comment | 27 complexity | 865e7da4158236756067801497a64d20 MD5 | raw file
Possible License(s): BSD-3-Clause
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}