|
- #include "flv-writer.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_writer_t
- {
- FILE* fp;
- flv_writer_onwrite write;
- void* param;
- };
-
- static int flv_write_header(int audio, int video, struct flv_writer_t* flv)
- {
- struct flv_vec_t vec[1];
- uint8_t header[FLV_HEADER_SIZE + 4];
- flv_header_write(audio, video, header, FLV_HEADER_SIZE);
- flv_tag_size_write(header + FLV_HEADER_SIZE, 4, 0); // PreviousTagSize0(Always 0)
- vec[0].ptr = header;
- vec[0].len = sizeof(header);
- return flv->write(flv->param, vec, 1);
- }
-
- static int flv_write_eos(struct flv_writer_t* flv)
- {
- int n;
- uint8_t header[16];
- struct flv_video_tag_header_t video;
- memset(&video, 0, sizeof(video));
- video.codecid = FLV_VIDEO_H264;
- video.keyframe = FLV_VIDEO_KEY_FRAME;
- video.avpacket = FLV_END_OF_SEQUENCE;
- video.cts = 0;
-
- n = flv_video_tag_header_write(&video, header, sizeof(header));
- return n > 0 ? flv_writer_input(flv, FLV_TYPE_VIDEO, header, n, 0) : -1;
- }
-
- static int file_write(void* param, const struct flv_vec_t* vec, int n)
- {
- int i;
- for(i = 0; i < n; i++)
- {
- if (vec[i].len != (int)fwrite(vec[i].ptr, 1, vec[i].len, (FILE*)param))
- return ferror((FILE*)param);
- }
- return 0;
- }
-
- void* flv_writer_create(const char* file)
- {
- FILE* fp;
- struct flv_writer_t* flv;
- fp = fopen(file, "wb");
- if (!fp)
- return NULL;
-
- flv = flv_writer_create2(1, 1, file_write, fp);
- if (!flv)
- {
- fclose(fp);
- return NULL;
- }
-
- flv->fp = fp;
- return flv;
- }
-
- void* flv_writer_create2(int audio, int video, flv_writer_onwrite write, void* param)
- {
- struct flv_writer_t* flv;
- flv = (struct flv_writer_t*)calloc(1, sizeof(*flv));
- if (!flv)
- return NULL;
-
- flv->write = write;
- flv->param = param;
- if (0 != flv_write_header(audio, video, flv))
- {
- flv_writer_destroy(flv);
- return NULL;
- }
-
- return flv;
- }
-
- void flv_writer_destroy(void* p)
- {
- struct flv_writer_t* flv;
- flv = (struct flv_writer_t*)p;
-
- if (NULL != flv)
- {
- flv_write_eos(flv);
- if (flv->fp)
- fclose(flv->fp);
- free(flv);
- }
- }
-
- int flv_writer_input(void* p, int type, const void* data, size_t bytes, uint32_t timestamp)
- {
- uint8_t buf[FLV_TAG_HEADER_SIZE + 4];
- struct flv_vec_t vec[3];
- struct flv_writer_t* flv;
- struct flv_tag_header_t tag;
- flv = (struct flv_writer_t*)p;
-
- memset(&tag, 0, sizeof(tag));
- tag.size = (int)bytes;
- tag.type = (uint8_t)type;
- tag.timestamp = timestamp;
- flv_tag_header_write(&tag, buf, FLV_TAG_HEADER_SIZE);
- flv_tag_size_write(buf + FLV_TAG_HEADER_SIZE, 4, (uint32_t)bytes + FLV_TAG_HEADER_SIZE);
-
- vec[0].ptr = buf; // FLV Tag Header
- vec[0].len = FLV_TAG_HEADER_SIZE;
- vec[1].ptr = (void*)data;
- vec[1].len = (int)bytes;
- vec[2].ptr = buf + FLV_TAG_HEADER_SIZE; // TAG size
- vec[2].len = 4;
- return flv->write(flv->param, vec, 3);
- }
-
- int flv_writer_input_v(void* p, int type, const struct flv_vec_t* v, int n, uint32_t timestamp)
- {
- int i;
- uint8_t buf[FLV_TAG_HEADER_SIZE + 4];
- struct flv_vec_t vec[8];
- struct flv_writer_t* flv;
- struct flv_tag_header_t tag;
- flv = (struct flv_writer_t*)p;
-
- memset(&tag, 0, sizeof(tag));
- tag.size = 0;
- tag.type = (uint8_t)type;
- tag.timestamp = timestamp;
-
- assert(n + 2 <= sizeof(vec) / sizeof(vec[0]));
- for (i = 0; i < n && i + 2 < sizeof(vec)/sizeof(vec[0]); i++)
- {
- tag.size += v[i].len;
- vec[i+1].ptr = v[i].ptr;
- vec[i+1].len = v[i].len;
- }
-
- vec[0].ptr = buf; // FLV Tag Header
- vec[0].len = FLV_TAG_HEADER_SIZE;
- vec[n + 1].ptr = buf + FLV_TAG_HEADER_SIZE; // TAG size
- vec[n + 1].len = 4;
-
- flv_tag_header_write(&tag, buf, FLV_TAG_HEADER_SIZE);
- flv_tag_size_write(buf + FLV_TAG_HEADER_SIZE, 4, (uint32_t)tag.size + FLV_TAG_HEADER_SIZE);
-
- return flv->write(flv->param, vec, n+2);
- }
|