Skip to content

Commit

Permalink
add FLV_VIDEO_SCREEN
Browse files Browse the repository at this point in the history
  • Loading branch information
ireader committed Oct 16, 2022
1 parent 74057b9 commit 0431d05
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 51 deletions.
39 changes: 32 additions & 7 deletions libflv/include/flv-proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,25 @@
#define FLV_TYPE_SCRIPT 18

// FLV Audio Type
#define FLV_AUDIO_LPCM (0 << 4) // Linear PCM, platform endian
#define FLV_AUDIO_ADPCM (1 << 4)
#define FLV_AUDIO_MP3 (2 << 4)
#define FLV_AUDIO_LLPCM (3 << 4) // Linear PCM, little endian
#define FLV_AUDIO_G711A (7 << 4) // G711 A-law
#define FLV_AUDIO_G711U (8 << 4) // G711 mu-law
#define FLV_AUDIO_AAC (10 << 4)
#define FLV_AUDIO_SPEEX (11 << 4)
#define FLV_AUDIO_OPUS (13 << 4)
#define FLV_AUDIO_MP3_8K (14 << 4)
#define FLV_AUDIO_MP3_8K (14 << 4) // MP3 8 kHz
#define FLV_AUDIO_DEVIDE (15 << 4) // Device-specific sound
#define FLV_AUDIO_ASC 0x100 // AudioSpecificConfig(ISO-14496-3)
#define FLV_AUDIO_OPUS_HEAD 0x101 // opus-codec.org

// FLV Video Type
#define FLV_VIDEO_H263 2
#define FLV_VIDEO_VP6 4
#define FLV_VIDEO_H264 7
#define FLV_VIDEO_H263 2 // Sorenson H.263
#define FLV_VIDEO_SCREEN 3 // Screen video
#define FLV_VIDEO_VP6 4 // On2 VP6
#define FLV_VIDEO_H264 7 // AVC
#define FLV_VIDEO_H265 12 // https://github.com/CDN-Union/H265
#define FLV_VIDEO_AV1 13 // https://aomediacodec.github.io/av1-isobmff
#define FLV_VIDEO_AVCC 0x200 // AVCDecoderConfigurationRecord(ISO-14496-15)
Expand All @@ -31,9 +36,9 @@

enum
{
FLV_SEQUENCE_HEADER = 0, // AVC/AAC sequence header
FLV_AVPACKET = 1, // AVC NALU / AAC raw
FLV_END_OF_SEQUENCE = 2, // AVC end of sequence (lower level NALU sequence ender is not required or supported)
FLV_SEQUENCE_HEADER = 0, // AVC/AAC sequence header
FLV_AVPACKET = 1, // AVC NALU / AAC raw
FLV_END_OF_SEQUENCE = 2, // AVC end of sequence (lower level NALU sequence ender is not required or supported)
};

enum
Expand All @@ -45,4 +50,24 @@ enum
FLV_VIDEO_COMMAND_FRAME = 5, // video info/command frame
};

enum
{
FLV_SOUND_RATE_5500 = 0, // 5.5 kHz
FLV_SOUND_RATE_11025 = 1, // 11 kHz
FLV_SOUND_RATE_22050 = 2, // 22 kHz
FLV_SOUND_RATE_44100 = 3, // 44 kHz
};

enum
{
FLV_SOUND_BIT_8 = 0, // 8-bit samples
FLV_SOUND_BIT_16 = 1, // 16-bit samples
};

enum
{
FLV_SOUND_CHANNEL_MONO = 0, // 1-channel
FLV_SOUND_CHANNEL_STEREO = 1, // 2-channels
};

#endif /* !_flv_proto_h_ */
82 changes: 39 additions & 43 deletions libflv/source/flv-muxer.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ struct flv_muxer_t
int update; // avc/hevc sequence header update

uint8_t* ptr;
int bytes;
int capacity;
size_t bytes;
size_t capacity;
};

struct flv_muxer_t* flv_muxer_create(flv_muxer_handler handler, void* param)
Expand Down Expand Up @@ -78,7 +78,7 @@ int flv_muxer_reset(struct flv_muxer_t* flv)
return 0;
}

static int flv_muxer_alloc(struct flv_muxer_t* flv, int bytes)
static int flv_muxer_alloc(struct flv_muxer_t* flv, size_t bytes)
{
void* p;
p = realloc(flv->ptr, bytes);
Expand All @@ -101,8 +101,8 @@ int flv_muxer_g711a(struct flv_muxer_t* flv, const void* data, size_t bytes, uin
return -ENOMEM;
}

audio.bits = 1; // 16-bit samples
audio.channels = 0;
audio.bits = FLV_SOUND_BIT_16; // 16-bit samples
audio.channels = FLV_SOUND_CHANNEL_MONO;
audio.rate = 0;
audio.codecid = FLV_AUDIO_G711A;
audio.avpacket = FLV_AVPACKET;
Expand All @@ -122,8 +122,8 @@ int flv_muxer_g711u(struct flv_muxer_t* flv, const void* data, size_t bytes, uin
return -ENOMEM;
}

audio.bits = 1; // 16-bit samples
audio.channels = 0;
audio.bits = FLV_SOUND_BIT_16; // 16-bit samples
audio.channels = FLV_SOUND_CHANNEL_MONO;
audio.rate = 0;
audio.codecid = FLV_AUDIO_G711U;
audio.avpacket = FLV_AVPACKET;
Expand All @@ -132,28 +132,26 @@ int flv_muxer_g711u(struct flv_muxer_t* flv, const void* data, size_t bytes, uin
return flv->handler(flv->param, FLV_TYPE_AUDIO, flv->ptr, bytes + 1, dts);
}

int flv_muxer_mp3(struct flv_muxer_t* flv, const void* data, size_t sz, uint32_t pts, uint32_t dts)
int flv_muxer_mp3(struct flv_muxer_t* flv, const void* data, size_t bytes, uint32_t pts, uint32_t dts)
{
int bytes;
struct mp3_header_t mp3;
struct flv_audio_tag_header_t audio;
(void)pts;

bytes = (int)sz;
if (0 == mp3_header_load(&mp3, data, bytes))
if (0 == mp3_header_load(&mp3, data, (int)bytes))
{
return -EINVAL;
}
else
{
audio.channels = 3 == mp3.mode ? 0 : 1;
audio.channels = 3 == mp3.mode ? FLV_SOUND_CHANNEL_MONO : FLV_SOUND_CHANNEL_STEREO;
switch (mp3_get_frequency(&mp3))
{
case 5500: audio.rate = 0; break;
case 11025: audio.rate = 1; break;
case 22050: audio.rate = 2; break;
case 44100: audio.rate = 3; break;
default: audio.rate = 3;
case 5500: audio.rate = FLV_SOUND_RATE_5500; break;
case 11025: audio.rate = FLV_SOUND_RATE_11025; break;
case 22050: audio.rate = FLV_SOUND_RATE_22050; break;
case 44100: audio.rate = FLV_SOUND_RATE_44100; break;
default: audio.rate = FLV_SOUND_RATE_44100;
}
}

Expand All @@ -163,21 +161,20 @@ int flv_muxer_mp3(struct flv_muxer_t* flv, const void* data, size_t sz, uint32_t
return -ENOMEM;
}

audio.bits = 1; // 16-bit samples
audio.bits = FLV_SOUND_BIT_16; // 16-bit samples
audio.codecid = FLV_AUDIO_MP3;
audio.avpacket = FLV_AVPACKET;
flv_audio_tag_header_write(&audio, flv->ptr, 1);
memcpy(flv->ptr + 1, data, bytes); // MP3
return flv->handler(flv->param, FLV_TYPE_AUDIO, flv->ptr, bytes + 1, dts);
}

int flv_muxer_aac(struct flv_muxer_t* flv, const void* data, size_t sz, uint32_t pts, uint32_t dts)
int flv_muxer_aac(struct flv_muxer_t* flv, const void* data, size_t bytes, uint32_t pts, uint32_t dts)
{
int r, n, m, bytes;
int r, n, m;
struct flv_audio_tag_header_t audio;
(void)pts;

bytes = (int)sz;
if (flv->capacity < bytes + 2/*AudioTagHeader*/ + 2/*AudioSpecificConfig*/)
{
if (0 != flv_muxer_alloc(flv, bytes + 4))
Expand All @@ -190,9 +187,9 @@ int flv_muxer_aac(struct flv_muxer_t* flv, const void* data, size_t sz, uint32_t
return -1; // invalid data

audio.codecid = FLV_AUDIO_AAC;
audio.rate = 3; // 44k-SoundRate
audio.bits = 1; // 16-bit samples
audio.channels = 1; // Stereo sound
audio.rate = FLV_SOUND_RATE_44100; // 44k-SoundRate
audio.bits = FLV_SOUND_BIT_16; // 16-bit samples
audio.channels = FLV_SOUND_CHANNEL_STEREO; // Stereo sound
if (0 == flv->audio_sequence_header)
{
flv->audio_sequence_header = 1; // once only
Expand All @@ -209,27 +206,26 @@ int flv_muxer_aac(struct flv_muxer_t* flv, const void* data, size_t sz, uint32_t
audio.avpacket = FLV_AVPACKET;
flv_audio_tag_header_write(&audio, flv->ptr, flv->capacity);
memcpy(flv->ptr + 2, (uint8_t*)data + n, bytes - n); // AAC exclude ADTS
assert(bytes - n + 2 <= (int)flv->capacity);
assert(bytes - n + 2 <= flv->capacity);
return flv->handler(flv->param, FLV_TYPE_AUDIO, flv->ptr, bytes - n + 2, dts);
}

int flv_muxer_opus(flv_muxer_t* flv, const void* data, size_t sz, uint32_t pts, uint32_t dts)
int flv_muxer_opus(flv_muxer_t* flv, const void* data, size_t bytes, uint32_t pts, uint32_t dts)
{
int r, m, bytes;
int r, m;
struct flv_audio_tag_header_t audio;
(void)pts;

bytes = (int)sz;
if (flv->capacity < bytes + 2/*AudioTagHeader*/ + 29/*OpusHead*/)
{
if (0 != flv_muxer_alloc(flv, bytes + 4))
return -ENOMEM;
}

audio.codecid = FLV_AUDIO_OPUS;
audio.rate = 3; // 44k-SoundRate
audio.bits = 1; // 16-bit samples
audio.channels = 1; // Stereo sound
audio.rate = FLV_SOUND_RATE_44100; // 44k-SoundRate
audio.bits = FLV_SOUND_BIT_16; // 16-bit samples
audio.channels = FLV_SOUND_CHANNEL_STEREO; // Stereo sound

if (0 == flv->audio_sequence_header)
{
Expand All @@ -250,7 +246,7 @@ int flv_muxer_opus(flv_muxer_t* flv, const void* data, size_t sz, uint32_t pts,
audio.avpacket = FLV_AVPACKET;
m = flv_audio_tag_header_write(&audio, flv->ptr, flv->capacity);
memcpy(flv->ptr + m, (uint8_t*)data, bytes);
assert(bytes - m <= (int)flv->capacity);
assert(bytes - m <= flv->capacity);
return flv->handler(flv->param, FLV_TYPE_AUDIO, flv->ptr, bytes + m, dts);
}

Expand All @@ -272,7 +268,7 @@ static int flv_muxer_h264(struct flv_muxer_t* flv, uint32_t pts, uint32_t dts)
return -1; // invalid data

flv->video_sequence_header = 1; // once only
assert(flv->bytes + m + 5 <= (int)flv->capacity);
assert(flv->bytes + m + 5 <= flv->capacity);
r = flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr + flv->bytes, m + 5, dts);
if (0 != r) return r;
}
Expand All @@ -284,22 +280,22 @@ static int flv_muxer_h264(struct flv_muxer_t* flv, uint32_t pts, uint32_t dts)
video.keyframe = 1 == flv->vcl ? FLV_VIDEO_KEY_FRAME : FLV_VIDEO_INTER_FRAME;
video.avpacket = FLV_AVPACKET;
flv_video_tag_header_write(&video, flv->ptr, flv->capacity);
assert(flv->bytes <= (int)flv->capacity);
assert(flv->bytes <= flv->capacity);
return flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr, flv->bytes, dts);
}
return 0;
}

int flv_muxer_avc(struct flv_muxer_t* flv, const void* data, size_t bytes, uint32_t pts, uint32_t dts)
{
if ((size_t)flv->capacity < bytes + sizeof(flv->v.avc) /*AVCDecoderConfigurationRecord*/)
if (flv->capacity < bytes + sizeof(flv->v.avc) /*AVCDecoderConfigurationRecord*/)
{
if (0 != flv_muxer_alloc(flv, (int)bytes + sizeof(flv->v.avc)))
if (0 != flv_muxer_alloc(flv, bytes + sizeof(flv->v.avc)))
return -ENOMEM;
}

flv->bytes = 5;
flv->bytes += h264_annexbtomp4(&flv->v.avc, data, (int)bytes, flv->ptr + flv->bytes, flv->capacity - flv->bytes, &flv->vcl, &flv->update);
flv->bytes += h264_annexbtomp4(&flv->v.avc, data, bytes, flv->ptr + flv->bytes, flv->capacity - flv->bytes, &flv->vcl, &flv->update);
if (flv->bytes <= 5)
return -ENOMEM;

Expand All @@ -324,7 +320,7 @@ static int flv_muxer_h265(struct flv_muxer_t* flv, uint32_t pts, uint32_t dts)
return -1; // invalid data

flv->video_sequence_header = 1; // once only
assert(flv->bytes + m + 5 <= (int)flv->capacity);
assert(flv->bytes + m + 5 <= flv->capacity);
r = flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr + flv->bytes, m + 5, dts);
if (0 != r) return r;
}
Expand All @@ -336,7 +332,7 @@ static int flv_muxer_h265(struct flv_muxer_t* flv, uint32_t pts, uint32_t dts)
video.keyframe = 1 == flv->vcl ? FLV_VIDEO_KEY_FRAME : FLV_VIDEO_INTER_FRAME;
video.avpacket = FLV_AVPACKET;
flv_video_tag_header_write(&video, flv->ptr, flv->capacity);
assert(flv->bytes <= (int)flv->capacity);
assert(flv->bytes <= flv->capacity);
return flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr, flv->bytes, dts);
}
return 0;
Expand All @@ -346,12 +342,12 @@ int flv_muxer_hevc(struct flv_muxer_t* flv, const void* data, size_t bytes, uint
{
if ((size_t)flv->capacity < bytes + sizeof(flv->v.hevc) /*HEVCDecoderConfigurationRecord*/)
{
if (0 != flv_muxer_alloc(flv, (int)bytes + sizeof(flv->v.hevc)))
if (0 != flv_muxer_alloc(flv, bytes + sizeof(flv->v.hevc)))
return -ENOMEM;
}

flv->bytes = 5;
flv->bytes += h265_annexbtomp4(&flv->v.hevc, data, (int)bytes, flv->ptr + flv->bytes, flv->capacity - flv->bytes, &flv->vcl, &flv->update);
flv->bytes += h265_annexbtomp4(&flv->v.hevc, data, bytes, flv->ptr + flv->bytes, flv->capacity - flv->bytes, &flv->vcl, &flv->update);
if (flv->bytes <= 5)
return -ENOMEM;

Expand All @@ -366,7 +362,7 @@ int flv_muxer_av1(flv_muxer_t* flv, const void* data, size_t bytes, uint32_t pts

if ((size_t)flv->capacity < bytes + 5 + sizeof(flv->v.av1) /*HEVCDecoderConfigurationRecord*/)
{
if (0 != flv_muxer_alloc(flv, (int)bytes + sizeof(flv->v.av1)))
if (0 != flv_muxer_alloc(flv, bytes + sizeof(flv->v.av1)))
return -ENOMEM;
}

Expand All @@ -387,7 +383,7 @@ int flv_muxer_av1(flv_muxer_t* flv, const void* data, size_t bytes, uint32_t pts
return -1; // invalid data

flv->video_sequence_header = 1; // once only
assert(flv->bytes + m + 5 <= (int)flv->capacity);
assert(flv->bytes + m + 5 <= flv->capacity);
r = flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr + flv->bytes, m + 5, dts);
if (0 != r) return r;
}
Expand Down
2 changes: 1 addition & 1 deletion libflv/source/flv-writer.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ static int flv_write_eos(struct flv_writer_t* flv)
struct flv_video_tag_header_t video;
memset(&video, 0, sizeof(video));
video.codecid = FLV_VIDEO_H264;
video.keyframe = 1;
video.keyframe = FLV_VIDEO_KEY_FRAME;
video.avpacket = FLV_END_OF_SEQUENCE;
video.cts = 0;

Expand Down

0 comments on commit 0431d05

Please sign in to comment.