You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

136 lines
2.9KB

  1. #include "flv-reader.h"
  2. #include "flv-header.h"
  3. #include "flv-proto.h"
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <assert.h>
  7. #include <stdio.h>
  8. #define FLV_HEADER_SIZE 9 // DataOffset included
  9. #define FLV_TAG_HEADER_SIZE 11 // StreamID included
  10. struct flv_reader_t
  11. {
  12. FILE* fp;
  13. int (*read)(void* param, void* buf, int len);
  14. void* param;
  15. };
  16. static int flv_read_header(struct flv_reader_t* flv)
  17. {
  18. uint32_t sz;
  19. uint8_t data[FLV_HEADER_SIZE];
  20. struct flv_header_t h;
  21. int n;
  22. if (FLV_HEADER_SIZE != flv->read(flv->param, data, FLV_HEADER_SIZE))
  23. return -1;
  24. if(FLV_HEADER_SIZE != flv_header_read(&h, data, FLV_HEADER_SIZE))
  25. return -1;
  26. assert(h.offset >= FLV_HEADER_SIZE && h.offset < FLV_HEADER_SIZE + 4096);
  27. for(n = (int)(h.offset - FLV_HEADER_SIZE); n > 0 && n < 4096; n -= sizeof(data))
  28. flv->read(flv->param, data, n >= sizeof(data) ? sizeof(data) : n); // skip
  29. // PreviousTagSize0
  30. if (4 != flv->read(flv->param, data, 4))
  31. return -1;
  32. flv_tag_size_read(data, 4, &sz);
  33. assert(0 == sz);
  34. return 0 == sz ? 0 : -1;
  35. }
  36. static int file_read(void* param, void* buf, int len)
  37. {
  38. return (int)fread(buf, 1, len, (FILE*)param);
  39. }
  40. void* flv_reader_create(const char* file)
  41. {
  42. FILE* fp;
  43. struct flv_reader_t* flv;
  44. fp = fopen(file, "rb");
  45. if (!fp)
  46. return NULL;
  47. flv = flv_reader_create2(file_read, fp);
  48. if (!flv)
  49. {
  50. fclose(fp);
  51. return NULL;
  52. }
  53. flv->fp = fp;
  54. return flv;
  55. }
  56. void* flv_reader_create2(int (*read)(void* param, void* buf, int len), void* param)
  57. {
  58. struct flv_reader_t* flv;
  59. flv = (struct flv_reader_t*)calloc(1, sizeof(*flv));
  60. if (!flv)
  61. return NULL;
  62. flv->read = read;
  63. flv->param = param;
  64. if (0 != flv_read_header(flv))
  65. {
  66. flv_reader_destroy(flv);
  67. return NULL;
  68. }
  69. return flv;
  70. }
  71. void flv_reader_destroy(void* p)
  72. {
  73. struct flv_reader_t* flv;
  74. flv = (struct flv_reader_t*)p;
  75. if (NULL != flv)
  76. {
  77. if (flv->fp)
  78. fclose(flv->fp);
  79. free(flv);
  80. }
  81. }
  82. int flv_reader_read(void* p, int* tagtype, uint32_t* timestamp, size_t* taglen, void* buffer, size_t bytes)
  83. {
  84. int r;
  85. uint32_t sz;
  86. uint8_t header[FLV_TAG_HEADER_SIZE];
  87. struct flv_tag_header_t tag;
  88. struct flv_reader_t* flv;
  89. flv = (struct flv_reader_t*)p;
  90. r = flv->read(flv->param, &header, FLV_TAG_HEADER_SIZE);
  91. if (r != FLV_TAG_HEADER_SIZE)
  92. return r < 0 ? r : 0; // 0-EOF
  93. if (FLV_TAG_HEADER_SIZE != flv_tag_header_read(&tag, header, FLV_TAG_HEADER_SIZE))
  94. return -1;
  95. if (bytes < tag.size)
  96. return -1;
  97. // FLV stream
  98. r = flv->read(flv->param, buffer, tag.size);
  99. if(tag.size != (uint32_t)r)
  100. return r < 0 ? r : 0; // 0-EOF
  101. // PreviousTagSizeN
  102. r = flv->read(flv->param, header, 4);
  103. if (4 != r)
  104. return r < 0 ? r : 0; // 0-EOF
  105. *taglen = tag.size;
  106. *tagtype = tag.type;
  107. *timestamp = tag.timestamp;
  108. flv_tag_size_read(header, 4, &sz);
  109. assert(0 == tag.streamId); // StreamID Always 0
  110. assert(sz == tag.size + FLV_TAG_HEADER_SIZE);
  111. return (sz == tag.size + FLV_TAG_HEADER_SIZE) ? 1 : -1;
  112. }