You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
KasmVNC/common/rfb/mp4_moof.c

195 lines
10 KiB
C

#include "mp4.h"
#include <string.h>
uint32_t pos_sequence_number = 0;
uint32_t pos_base_data_offset = 0;
uint32_t pos_base_media_decode_time = 0;
struct DataOffsetPos {
bool data_offset_present;
uint32_t offset;
};
enum BufError write_mfhd(struct BitBuf *ptr, const uint32_t sequence_number);
enum BufError write_traf(struct BitBuf *ptr,
const uint32_t sequence_number,
const uint64_t base_data_offset,
const uint64_t base_media_decode_time,
const uint32_t default_sample_duration,
const struct SampleInfo *samples_info, const uint32_t samples_info_len,
struct DataOffsetPos *data_offset);
enum BufError write_tfhd(struct BitBuf *ptr,
const uint32_t sequence_number,
const uint64_t base_data_offset,
const uint64_t base_media_decode_time,
const uint32_t default_sample_size,
const uint32_t default_sample_duration,
const struct SampleInfo *samples_info, const uint32_t samples_info_len,
struct DataOffsetPos *data_offset);
enum BufError write_tfdt(struct BitBuf *ptr, const uint64_t base_media_decode_time);
enum BufError write_trun(struct BitBuf *ptr,
const struct SampleInfo *samples_info, const uint32_t samples_info_count,
struct DataOffsetPos *data_offset);
enum BufError write_mdat(struct BitBuf *ptr, const uint8_t* data, const uint32_t origlen, const uint32_t len) {
enum BufError err;
uint32_t start_atom = ptr->offset; err = put_u32_be(ptr, 0); chk_err; err = put_str4(ptr, "mdat"); chk_err
err = put_u32_be(ptr, origlen); chk_err // todo
// printf(" write_mdat: "); for (int i = 0; i < 32; ++i) printf(" 0x%02hhX", data[i]); printf("\n");
err = put(ptr, data, len); chk_err
// printf("mdat len %d ptr->offset %d start_atom: %d \n", len, ptr->offset, start_atom);
err = put_u32_be_to_offset(ptr, start_atom, ptr->offset - start_atom); chk_err
return BUF_OK;
}
enum BufError write_moof(struct BitBuf *ptr,
const uint32_t sequence_number,
const uint64_t base_data_offset,
const uint64_t base_media_decode_time,
const uint32_t default_sample_duration,
const struct SampleInfo *samples_info, const uint32_t samples_info_len)
{
enum BufError err;
uint32_t start_atom = ptr->offset; err = put_u32_be(ptr, 0); chk_err; err = put_str4(ptr, "moof"); chk_err
err = write_mfhd(ptr, sequence_number); chk_err
struct DataOffsetPos data_offset;
data_offset.offset = 0;
err = write_traf(ptr, sequence_number, base_data_offset, base_media_decode_time, default_sample_duration, samples_info, samples_info_len, &data_offset); chk_err
if (data_offset.data_offset_present)
err = put_u32_be_to_offset(ptr, data_offset.offset, ptr->offset + 4 /*mdat size*/ + 4 /*mdat id*/); chk_err
err = put_u32_be_to_offset(ptr, start_atom, ptr->offset - start_atom); chk_err
return BUF_OK;
}
enum BufError write_mfhd(struct BitBuf *ptr, const uint32_t sequence_number) {
enum BufError err;
uint32_t start_atom = ptr->offset; err = put_u32_be(ptr, 0); chk_err; err = put_str4(ptr, "mfhd"); chk_err
err = put_u8(ptr, 0); // 1 version
err = put_u8(ptr, 0); chk_err; err = put_u8(ptr, 0); chk_err; err = put_u8(ptr, 0); chk_err // 3 flags
pos_sequence_number = ptr->offset;
err = put_u32_be(ptr, sequence_number); chk_err // 4 sequence_number
err = put_u32_be_to_offset(ptr, start_atom, ptr->offset - start_atom); chk_err
return BUF_OK;
}
enum BufError write_traf(struct BitBuf *ptr,
const uint32_t sequence_number,
const uint64_t base_data_offset,
const uint64_t base_media_decode_time,
const uint32_t default_sample_duration,
const struct SampleInfo *samples_info, const uint32_t samples_info_len,
struct DataOffsetPos *data_offset)
{
enum BufError err;
uint32_t start_atom = ptr->offset; err = put_u32_be(ptr, 0); chk_err; err = put_str4(ptr, "traf"); chk_err
err = write_tfhd(ptr, sequence_number, base_data_offset, base_media_decode_time, samples_info[0].size, default_sample_duration, samples_info, samples_info_len, data_offset); chk_err
err = write_tfdt(ptr, base_media_decode_time); chk_err
err = write_trun(ptr, samples_info, samples_info_len, data_offset); chk_err
err = put_u32_be_to_offset(ptr, start_atom, ptr->offset - start_atom); chk_err
return BUF_OK;
}
enum BufError write_tfhd(struct BitBuf *ptr,
const uint32_t sequence_number,
const uint64_t base_data_offset,
const uint64_t base_media_decode_time,
const uint32_t default_sample_size,
const uint32_t default_sample_duration,
const struct SampleInfo *samples_info, const uint32_t samples_info_len,
struct DataOffsetPos *data_offset)
{
enum BufError err;
uint32_t start_atom = ptr->offset; err = put_u32_be(ptr, 0); chk_err; err = put_str4(ptr, "tfhd"); chk_err
err = put_u8(ptr, 0); chk_err // 1 byte version
uint64_t flags = 0x0;
const bool base_data_offset_present = false;
const bool sample_description_index_present = false;
const bool default_sample_duration_present = true;
const bool default_sample_size_present = true;
const bool default_sample_flags_present = true;
const bool duration_is_empty = false;
const bool default_base_is_moof = false;
if (base_data_offset_present) { flags = flags | 0x000001; } // base-data-offset-present
if (sample_description_index_present) { flags = flags | 0x000002; } // sample-description-index-present
if (default_sample_duration_present) { flags = flags | 0x000008; } // default-sample-duration-present
if (default_sample_size_present) { flags = flags | 0x000010; } // default-sample-size-present
if (default_sample_flags_present) { flags = flags | 0x000020; } // default-sample-flags-present
if (duration_is_empty) { flags = flags | 0x010000; } // duration-is-empty
if (default_base_is_moof) { flags = flags | 0x020000; } // default-base-is-moof
// buf.put_u8(0); buf.put_u8(0); buf.put_u8(0x39); // 3 flags
// println!("tfhd flags: 0x{:06x} 0x{:02x}: 0x{:02x}: 0x{:02x}", flags, (flags >> 16) as u8, (flags >> 8) as u8, (flags >> 0) as u8);
err = put_u8(ptr, flags >> 16); chk_err; err = put_u8(ptr, flags >> 8); chk_err; err = put_u8(ptr, flags >> 0); chk_err // 3 flags
err = put_u32_be(ptr, 1); chk_err // 4 track_ID
if (base_data_offset_present) { pos_base_data_offset = ptr->offset; err = put_u64_be(ptr, base_data_offset); chk_err }
// if sample_description_index_present { buf.put_u32_be(0); } // 4 default_sample_description_index
if (default_sample_duration_present) { err = put_u32_be(ptr, default_sample_duration); chk_err }
if (default_sample_size_present) { err = put_u32_be(ptr, default_sample_size); chk_err }
if (default_sample_flags_present) { err = put_u32_be(ptr, 16842752); chk_err }
err = put_u32_be_to_offset(ptr, start_atom, ptr->offset - start_atom); chk_err
return BUF_OK;
}
enum BufError write_tfdt(struct BitBuf *ptr, const uint64_t base_media_decode_time) {
enum BufError err;
uint32_t start_atom = ptr->offset; err = put_u32_be(ptr, 0); chk_err; err = put_str4(ptr, "tfdt"); chk_err
err = put_u8(ptr, 1); // 1 version
err = put_u8(ptr, 0); chk_err; err = put_u8(ptr, 0); chk_err; err = put_u8(ptr, 0); chk_err // 3 flags
pos_base_media_decode_time = ptr->offset;
err = put_u64_be(ptr, base_media_decode_time); chk_err // 4 baseMediaDecodeTime
err = put_u32_be_to_offset(ptr, start_atom, ptr->offset - start_atom); chk_err
return BUF_OK;
}
enum BufError write_trun(struct BitBuf *ptr,
const struct SampleInfo *samples_info, const uint32_t samples_info_count,
struct DataOffsetPos *data_offset)
{
enum BufError err;
uint32_t start_atom = ptr->offset; err = put_u32_be(ptr, 0); chk_err; err = put_str4(ptr, "trun"); chk_err
err = put_u8(ptr, 0); chk_err // 1 version
const bool data_offset_present = true;
const bool first_sample_flags_present = false;
const bool sample_duration_present = true;
const bool sample_size_present = true;
const bool sample_flags_present = true;
const bool sample_composition_time_offsets_present = true;
{
uint64_t flags = 0x0;
if (data_offset_present) { flags = flags | 0x000001; } // 0x000001 data-offset-present.
if (first_sample_flags_present) { flags = flags | 0x000004; } // 0x000004 first-sample-flags-present
if (sample_duration_present) { flags = flags | 0x000100; } // 0x000100 sample-duration-present
if (sample_size_present) { flags = flags | 0x000200; } // 0x000200 sample-size-present
if (sample_flags_present) { flags = flags | 0x000400; } // 0x000400 sample-flags-present
if (sample_composition_time_offsets_present) { flags = flags | 0x000800; } // 0x000800 sample-composition-time-offsets-present
// println!("trup flags: 0x{:06x} 0x{:02x}: 0x{:02x}: 0x{:02x}", flags, (flags >> 16) as u8, (flags >> 8) as u8, (flags >> 0) as u8);
err = put_u8(ptr, flags >> 16); chk_err; err = put_u8(ptr, flags >> 8); chk_err; err = put_u8(ptr, flags >> 0); chk_err // 3 flags
}
err = put_u32_be(ptr, samples_info_count); chk_err // 4 sample_count
data_offset->data_offset_present = data_offset_present;
data_offset->offset = ptr->offset; // save pointer to this place. we will change size after moof atom will created
if (data_offset_present) { err = put_i32_be(ptr, 0); chk_err } // 4 fake data_offset
if (first_sample_flags_present) { err = put_u32_be(ptr, 33554432); chk_err } // 4 first_sample_flags
for (uint32_t i = 0; i < samples_info_count; ++i) {
const struct SampleInfo sample_info = samples_info[i];
if (sample_duration_present) { err = put_u32_be(ptr, sample_info.duration); chk_err } // 4 sample_duration
if (sample_size_present) { err = put_u32_be(ptr, sample_info.size); chk_err } // 4 sample_size
if (sample_flags_present) { err = put_u32_be(ptr, sample_info.flags); chk_err } // 4 sample_flags
if (sample_composition_time_offsets_present) {
// if version == 0 { err = put_u32_be(ptr, sample_info.composition_offset as u32); chk_err }
// else
{ err = put_i32_be(ptr, sample_info.composition_offset); chk_err }
}
}
err = put_u32_be_to_offset(ptr, start_atom, ptr->offset - start_atom); chk_err
return BUF_OK;
}