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