Older/MediaServer/libflv/source/flv-reader.c

136 lines
2.9 KiB
C
Raw Normal View History

2024-10-01 00:12:57 +08:00
#include "flv-reader.h"
#include "flv-header.h"
#include "flv-proto.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#define FLV_HEADER_SIZE 9 // DataOffset included
#define FLV_TAG_HEADER_SIZE 11 // StreamID included
struct flv_reader_t
{
FILE* fp;
int (*read)(void* param, void* buf, int len);
void* param;
};
static int flv_read_header(struct flv_reader_t* flv)
{
uint32_t sz;
uint8_t data[FLV_HEADER_SIZE];
struct flv_header_t h;
int n;
if (FLV_HEADER_SIZE != flv->read(flv->param, data, FLV_HEADER_SIZE))
return -1;
if(FLV_HEADER_SIZE != flv_header_read(&h, data, FLV_HEADER_SIZE))
return -1;
assert(h.offset >= FLV_HEADER_SIZE && h.offset < FLV_HEADER_SIZE + 4096);
for(n = (int)(h.offset - FLV_HEADER_SIZE); n > 0 && n < 4096; n -= sizeof(data))
flv->read(flv->param, data, n >= sizeof(data) ? sizeof(data) : n); // skip
// PreviousTagSize0
if (4 != flv->read(flv->param, data, 4))
return -1;
flv_tag_size_read(data, 4, &sz);
assert(0 == sz);
return 0 == sz ? 0 : -1;
}
static int file_read(void* param, void* buf, int len)
{
return (int)fread(buf, 1, len, (FILE*)param);
}
void* flv_reader_create(const char* file)
{
FILE* fp;
struct flv_reader_t* flv;
fp = fopen(file, "rb");
if (!fp)
return NULL;
flv = flv_reader_create2(file_read, fp);
if (!flv)
{
fclose(fp);
return NULL;
}
flv->fp = fp;
return flv;
}
void* flv_reader_create2(int (*read)(void* param, void* buf, int len), void* param)
{
struct flv_reader_t* flv;
flv = (struct flv_reader_t*)calloc(1, sizeof(*flv));
if (!flv)
return NULL;
flv->read = read;
flv->param = param;
if (0 != flv_read_header(flv))
{
flv_reader_destroy(flv);
return NULL;
}
return flv;
}
void flv_reader_destroy(void* p)
{
struct flv_reader_t* flv;
flv = (struct flv_reader_t*)p;
if (NULL != flv)
{
if (flv->fp)
fclose(flv->fp);
free(flv);
}
}
int flv_reader_read(void* p, int* tagtype, uint32_t* timestamp, size_t* taglen, void* buffer, size_t bytes)
{
int r;
uint32_t sz;
uint8_t header[FLV_TAG_HEADER_SIZE];
struct flv_tag_header_t tag;
struct flv_reader_t* flv;
flv = (struct flv_reader_t*)p;
r = flv->read(flv->param, &header, FLV_TAG_HEADER_SIZE);
if (r != FLV_TAG_HEADER_SIZE)
return r < 0 ? r : 0; // 0-EOF
if (FLV_TAG_HEADER_SIZE != flv_tag_header_read(&tag, header, FLV_TAG_HEADER_SIZE))
return -1;
if (bytes < tag.size)
return -1;
// FLV stream
r = flv->read(flv->param, buffer, tag.size);
if(tag.size != (uint32_t)r)
return r < 0 ? r : 0; // 0-EOF
// PreviousTagSizeN
r = flv->read(flv->param, header, 4);
if (4 != r)
return r < 0 ? r : 0; // 0-EOF
*taglen = tag.size;
*tagtype = tag.type;
*timestamp = tag.timestamp;
flv_tag_size_read(header, 4, &sz);
assert(0 == tag.streamId); // StreamID Always 0
assert(sz == tag.size + FLV_TAG_HEADER_SIZE);
return (sz == tag.size + FLV_TAG_HEADER_SIZE) ? 1 : -1;
}