Skip to content

Commit

Permalink
feat: flv muxer callback memory valid
Browse files Browse the repository at this point in the history
  • Loading branch information
ireader committed Oct 20, 2024
2 parents 0c5c1b6 + 6d785f1 commit 95fe593
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 73 deletions.
152 changes: 79 additions & 73 deletions libflv/source/flv-muxer.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,13 @@ int flv_muxer_mp3(struct flv_muxer_t* flv, const void* data, size_t bytes, uint3

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;
int r, n, m, k;
struct flv_audio_tag_header_t audio;
(void)pts;

if (flv->capacity < bytes + 2/*AudioTagHeader*/ + 2/*AudioSpecificConfig*/)
if (flv->capacity < bytes + 5 /*AudioTagHeader*/ + 8 /*AudioSpecificConfig*/)
{
if (0 != flv_muxer_alloc(flv, bytes + 4))
if (0 != flv_muxer_alloc(flv, bytes + 5 + 8))
return -ENOMEM;
}

Expand All @@ -200,6 +200,7 @@ int flv_muxer_aac(struct flv_muxer_t* flv, const void* data, size_t bytes, uint3
if (n <= 0)
return -1; // invalid data

m = 0;
audio.codecid = FLV_AUDIO_AAC;
audio.rate = FLV_SOUND_RATE_44100; // 44k-SoundRate
audio.bits = FLV_SOUND_BIT_16; // 16-bit samples
Expand All @@ -210,23 +211,23 @@ int flv_muxer_aac(struct flv_muxer_t* flv, const void* data, size_t bytes, uint3
audio.avpacket = FLV_SEQUENCE_HEADER;

// AudioSpecificConfig(AAC sequence header)
flv_audio_tag_header_write(&audio, flv->ptr, flv->capacity);
m = mpeg4_aac_audio_specific_config_save(&flv->a.aac, flv->ptr + 2, flv->capacity - 2);
assert(m + 2 <= (int)flv->capacity);
r = flv->handler(flv->param, FLV_TYPE_AUDIO, flv->ptr, m + 2, dts);
m = flv_audio_tag_header_write(&audio, flv->ptr, flv->capacity);
m += mpeg4_aac_audio_specific_config_save(&flv->a.aac, flv->ptr + m, flv->capacity - m - ((bytes - n) + m));
assert(m <= (int)flv->capacity);
r = flv->handler(flv->param, FLV_TYPE_AUDIO, flv->ptr, m, dts);
if (0 != r) return r;
}

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 <= flv->capacity);
return flv->handler(flv->param, FLV_TYPE_AUDIO, flv->ptr, bytes - n + 2, dts);
k = flv_audio_tag_header_write(&audio, flv->ptr + m /*asc*/, flv->capacity - m);
assert(m + k + bytes - n <= flv->capacity);
memcpy(flv->ptr + m /*asc*/ + k /*tag*/, (uint8_t*)data + n, bytes - n); // AAC exclude ADTS
return flv->handler(flv->param, FLV_TYPE_AUDIO, flv->ptr + m, k + bytes - n, dts);
}

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

Expand All @@ -236,6 +237,7 @@ int flv_muxer_opus(flv_muxer_t* flv, const void* data, size_t bytes, uint32_t pt
return -ENOMEM;
}

m = 0;
audio.codecid = FLV_AUDIO_OPUS;
audio.rate = FLV_SOUND_RATE_44100; // 44k-SoundRate
audio.bits = FLV_SOUND_BIT_16; // 16-bit samples
Expand All @@ -251,59 +253,61 @@ int flv_muxer_opus(flv_muxer_t* flv, const void* data, size_t bytes, uint32_t pt

// Opus Head
m = flv_audio_tag_header_write(&audio, flv->ptr, flv->capacity);
m += opus_head_save(&flv->a.opus, flv->ptr+m, flv->capacity-m);
m += opus_head_save(&flv->a.opus, flv->ptr+m, flv->capacity-m-(bytes+m));
assert(m <= (int)flv->capacity);
r = flv->handler(flv->param, FLV_TYPE_AUDIO, flv->ptr, m, dts);
if (0 != r) return r;
}

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 <= flv->capacity);
return flv->handler(flv->param, FLV_TYPE_AUDIO, flv->ptr, bytes + m, dts);
n = flv_audio_tag_header_write(&audio, flv->ptr + m /*seq*/, flv->capacity - m);
assert(m + n + bytes <= flv->capacity);
memcpy(flv->ptr + m /*seq*/ + n /*tag*/, (uint8_t*)data, bytes);
return flv->handler(flv->param, FLV_TYPE_AUDIO, flv->ptr + m, bytes + n, dts);
}

int flv_muxer_ac3(struct flv_muxer_t* flv, const void* data, size_t bytes, uint32_t pts, uint32_t dts)
{
int k;
struct flv_audio_tag_header_t audio;
(void)pts;

if (flv->capacity < bytes + 1)
if (flv->capacity < bytes + 5 /*enhanced*/)
{
if (0 != flv_muxer_alloc(flv, bytes + 4))
if (0 != flv_muxer_alloc(flv, bytes + 5))
return -ENOMEM;
}

audio.codecid = FLV_AUDIO_AC3;
audio.avpacket = FLV_AVPACKET;
flv_audio_tag_header_write(&audio, flv->ptr, 1);
memcpy(flv->ptr + 1, data, bytes);
return flv->handler(flv->param, FLV_TYPE_AUDIO, flv->ptr, bytes + 1, dts);
k = flv_audio_tag_header_write(&audio, flv->ptr, flv->capacity-bytes);
memcpy(flv->ptr + k, data, bytes);
return flv->handler(flv->param, FLV_TYPE_AUDIO, flv->ptr, bytes + k, dts);
}

int flv_muxer_eac3(struct flv_muxer_t* flv, const void* data, size_t bytes, uint32_t pts, uint32_t dts)
{
int k;
struct flv_audio_tag_header_t audio;
(void)pts;

if (flv->capacity < bytes + 1)
if (flv->capacity < bytes + 5 /*enhanced*/)
{
if (0 != flv_muxer_alloc(flv, bytes + 4))
if (0 != flv_muxer_alloc(flv, bytes + 5))
return -ENOMEM;
}

audio.codecid = FLV_AUDIO_EAC3;
audio.avpacket = FLV_AVPACKET;
flv_audio_tag_header_write(&audio, flv->ptr, 1);
memcpy(flv->ptr + 1, data, bytes);
return flv->handler(flv->param, FLV_TYPE_AUDIO, flv->ptr, bytes + 1, dts);
k = flv_audio_tag_header_write(&audio, flv->ptr, flv->capacity - bytes);
memcpy(flv->ptr + k, data, bytes);
return flv->handler(flv->param, FLV_TYPE_AUDIO, flv->ptr, bytes + k, dts);
}

static int flv_muxer_h264(struct flv_muxer_t* flv, uint32_t pts, uint32_t dts)
{
int r;
int m;
int m, n;
struct flv_video_tag_header_t video;

video.codecid = FLV_VIDEO_H264;
Expand All @@ -313,14 +317,14 @@ static int flv_muxer_h264(struct flv_muxer_t* flv, uint32_t pts, uint32_t dts)
video.cts = 0;
video.keyframe = 1; // keyframe
video.avpacket = FLV_SEQUENCE_HEADER;
flv_video_tag_header_write(&video, flv->ptr + flv->bytes, flv->capacity - flv->bytes);
m = mpeg4_avc_decoder_configuration_record_save(&flv->v.avc, flv->ptr + flv->bytes + 5, flv->capacity - flv->bytes - 5);
if (m <= 0)
n = flv_video_tag_header_write(&video, flv->ptr + flv->bytes, flv->capacity - flv->bytes);
m = mpeg4_avc_decoder_configuration_record_save(&flv->v.avc, flv->ptr + flv->bytes + n, flv->capacity - flv->bytes - n);
if (m <= 0 || n < 0)
return -1; // invalid data

flv->video_sequence_header = 1; // once only
assert(flv->bytes + m + 5 <= flv->capacity);
r = flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr + flv->bytes, m + 5, dts);
assert(flv->bytes + m + n <= flv->capacity);
r = flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr + flv->bytes, m + n, dts);
if (0 != r) return r;
}

Expand All @@ -330,18 +334,18 @@ static int flv_muxer_h264(struct flv_muxer_t* flv, uint32_t pts, uint32_t dts)
video.cts = pts - 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 <= flv->capacity);
n = flv_video_tag_header_write(&video, flv->ptr, flv->capacity);
assert(n == 5);
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 (flv->capacity < bytes + sizeof(flv->v.avc) /*AVCDecoderConfigurationRecord*/)
if (flv->capacity < bytes + 5 + sizeof(flv->v.avc) /*AVCDecoderConfigurationRecord*/)
{
if (0 != flv_muxer_alloc(flv, bytes + sizeof(flv->v.avc)))
if (0 != flv_muxer_alloc(flv, bytes + 5 + sizeof(flv->v.avc)))
return -ENOMEM;
}

Expand All @@ -368,7 +372,7 @@ static int flv_muxer_h265(struct flv_muxer_t* flv, uint32_t pts, uint32_t dts)
video.avpacket = FLV_SEQUENCE_HEADER;
n = flv_video_tag_header_write(&video, flv->ptr + flv->bytes, flv->capacity - flv->bytes);
m = mpeg4_hevc_decoder_configuration_record_save(&flv->v.hevc, flv->ptr + flv->bytes + n, flv->capacity - flv->bytes - n);
if (m <= 0)
if (m <= 0 || n < 0)
return -1; // invalid data

flv->video_sequence_header = 1; // once only
Expand All @@ -384,23 +388,21 @@ 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;
n = flv_video_tag_header_write(&video, flv->ptr, flv->capacity);
assert(flv->bytes <= flv->capacity);
assert(n == 5 + (flv->enhanced_rtmp && dts == pts) ? 0 : 3);
return flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr, flv->bytes, dts);
}
return 0;
}

int flv_muxer_hevc(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.hevc) /*HEVCDecoderConfigurationRecord*/)
if ((size_t)flv->capacity < bytes + 8 /*enhanced*/ + sizeof(flv->v.hevc) /*HEVCDecoderConfigurationRecord*/)
{
if (0 != flv_muxer_alloc(flv, bytes + sizeof(flv->v.hevc)))
if (0 != flv_muxer_alloc(flv, bytes + 8 + sizeof(flv->v.hevc)))
return -ENOMEM;
}

flv->bytes = 5;
if(flv->enhanced_rtmp)
flv->bytes += dts == pts ? 0 : 3;
flv->bytes = 5 + (flv->enhanced_rtmp && dts == pts) ? 0 : 3;
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 @@ -423,7 +425,7 @@ static int flv_muxer_h266(struct flv_muxer_t* flv, uint32_t pts, uint32_t dts)
video.avpacket = FLV_SEQUENCE_HEADER;
n = flv_video_tag_header_write(&video, flv->ptr + flv->bytes, flv->capacity - flv->bytes);
m = mpeg4_vvc_decoder_configuration_record_save(&flv->v.vvc, flv->ptr + flv->bytes + n, flv->capacity - flv->bytes - n);
if (m <= 0)
if (m <= 0 || n < 0)
return -1; // invalid data

flv->video_sequence_header = 1; // once only
Expand All @@ -439,23 +441,21 @@ static int flv_muxer_h266(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;
n = flv_video_tag_header_write(&video, flv->ptr, flv->capacity);
assert(flv->bytes <= flv->capacity);
assert(n == 5 + (flv->enhanced_rtmp && dts == pts) ? 0 : 3);
return flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr, flv->bytes, dts);
}
return 0;
}

int flv_muxer_vvc(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.vvc) /*HEVCDecoderConfigurationRecord*/)
if ((size_t)flv->capacity < bytes + 8 /*enhanced*/ + sizeof(flv->v.vvc) /*HEVCDecoderConfigurationRecord*/)
{
if (0 != flv_muxer_alloc(flv, bytes + sizeof(flv->v.vvc)))
if (0 != flv_muxer_alloc(flv, bytes + 8 + sizeof(flv->v.vvc)))
return -ENOMEM;
}

flv->bytes = 5;
if(flv->enhanced_rtmp)
flv->bytes += dts == pts ? 0 : 3;
flv->bytes = 5 + (flv->enhanced_rtmp && dts == pts) ? 0 : 3;
flv->bytes += h266_annexbtomp4(&flv->v.vvc, data, bytes, flv->ptr + flv->bytes, flv->capacity - flv->bytes, &flv->vcl, &flv->update);
if (flv->bytes <= 5)
return -ENOMEM;
Expand All @@ -466,15 +466,16 @@ int flv_muxer_vvc(struct flv_muxer_t* flv, const void* data, size_t bytes, uint3
int flv_muxer_av1(flv_muxer_t* flv, const void* data, size_t bytes, uint32_t pts, uint32_t dts)
{
int r;
int m;
int m, n;
struct flv_video_tag_header_t video;

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

m = 0;
video.codecid = FLV_VIDEO_AV1;
video.enhanced_rtmp = flv->enhanced_rtmp;
if (0 == flv->video_sequence_header)
Expand All @@ -487,15 +488,16 @@ int flv_muxer_av1(flv_muxer_t* flv, const void* data, size_t bytes, uint32_t pts
video.cts = 0;
video.keyframe = 1; // keyframe
video.avpacket = FLV_SEQUENCE_HEADER;
flv_video_tag_header_write(&video, flv->ptr + flv->bytes, flv->capacity - flv->bytes);
m = aom_av1_codec_configuration_record_save(&flv->v.av1, flv->ptr + flv->bytes + 5, flv->capacity - flv->bytes - 5);
if (m <= 0)
n = flv_video_tag_header_write(&video, flv->ptr, flv->capacity);
m = aom_av1_codec_configuration_record_save(&flv->v.av1, flv->ptr + n, flv->capacity - n - (bytes + n));
if (m <= 0 || n < 0)
return -1; // invalid data

flv->video_sequence_header = 1; // once only
assert(flv->bytes + m + 5 <= flv->capacity);
r = flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr + flv->bytes, m + 5, dts);
assert(m + n <= flv->capacity);
r = flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr, m + n, dts);
if (0 != r) return r;
m += n;
}

// has video frame
Expand All @@ -504,25 +506,27 @@ int flv_muxer_av1(flv_muxer_t* flv, const void* data, size_t bytes, uint32_t pts
video.cts = pts - 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);
memcpy(flv->ptr + 5, data, bytes);
return flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr, bytes + 5, dts);
n = flv_video_tag_header_write(&video, flv->ptr + m /*seq*/, flv->capacity - m);
assert(m + n + bytes <= flv->capacity);
memcpy(flv->ptr + m /*seq*/ + n /*tag*/, data, bytes);
return flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr + m /*seq*/, bytes + n, dts);
}
return 0;
}

int flv_muxer_avs3(flv_muxer_t* flv, const void* data, size_t bytes, uint32_t pts, uint32_t dts)
{
int r;
int m;
int m, n;
struct flv_video_tag_header_t video;

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

m = 0;
video.codecid = FLV_VIDEO_H266; // codec 14, same as H.266
video.enhanced_rtmp = flv->enhanced_rtmp;
if (0 == flv->video_sequence_header)
Expand All @@ -535,15 +539,16 @@ int flv_muxer_avs3(flv_muxer_t* flv, const void* data, size_t bytes, uint32_t pt
video.cts = 0;
video.keyframe = 1; // keyframe
video.avpacket = FLV_SEQUENCE_HEADER;
flv_video_tag_header_write(&video, flv->ptr + flv->bytes, flv->capacity - flv->bytes);
m = avswg_avs3_decoder_configuration_record_save(&flv->v.avs3, flv->ptr + flv->bytes + 5, flv->capacity - flv->bytes - 5);
if (m <= 0)
n = flv_video_tag_header_write(&video, flv->ptr, flv->capacity);
m = avswg_avs3_decoder_configuration_record_save(&flv->v.avs3, flv->ptr + n, flv->capacity - n - bytes - n);
if (m <= 0 || n < 0)
return -1; // invalid data

assert(m + n <= flv->capacity);
flv->video_sequence_header = 1; // once only
assert(flv->bytes + m + 5 <= flv->capacity);
r = flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr + flv->bytes, m + 5, dts);
r = flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr, m + n, dts);
if (0 != r) return r;
m += n;
}

// has video frame
Expand All @@ -552,9 +557,10 @@ int flv_muxer_avs3(flv_muxer_t* flv, const void* data, size_t bytes, uint32_t pt
video.cts = pts - 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);
memcpy(flv->ptr + 5, data, bytes);
return flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr, bytes + 5, dts);
n = flv_video_tag_header_write(&video, flv->ptr + m /*seq*/, flv->capacity - m);
assert(m + n + bytes <= flv->capacity);
memcpy(flv->ptr + m /*seq*/ + n /*tag*/, data, bytes);
return flv->handler(flv->param, FLV_TYPE_VIDEO, flv->ptr + m /*seq*/, bytes + n, dts);
}
return 0;
}
Expand Down
3 changes: 3 additions & 0 deletions libflv/source/mpeg4-vvc.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ int mpeg4_vvc_decoder_configuration_record_load(const uint8_t* data, size_t byte
uint16_t i, j, k, n, numOfArrays;
uint8_t* dst;

if (bytes < 2)
return -1;

vvc->off = 0; // clear
mpeg4_bits_init(&bits, (void*)data, bytes);
mpeg4_bits_read_n(&bits, 5); // reserved '11111'b
Expand Down

0 comments on commit 95fe593

Please sign in to comment.