📄 main.c
字号:
} } /*move to current time in TS unit*/ stream->time = stream->program->pcr_init_ts_time; m2ts_time_inc(&stream->time, (u32) (stream->pck.dts - stream->program->pcr_init_time), 90000); /*compute bitrate if needed*/ if (!stream->bit_rate) { if (!stream->last_br_time) { stream->last_br_time = stream->pck.dts + 1; stream->bytes_since_last_time = stream->pck.data_len; } else { if (stream->pck.dts - stream->last_br_time - 1 >= 90000) { u64 r = 8*stream->bytes_since_last_time; r*=90000; stream->bit_rate = (u32) (r / (stream->pck.dts - stream->last_br_time - 1)); stream->program->mux->needs_reconfig = 1; } else { stream->bytes_since_last_time += stream->pck.data_len; } } } } return 1;}#define PES_HEADER_LENGTH 19u32 m2ts_stream_add_pes_header(GF_BitStream *bs, M2TS_Mux_Stream *stream, Bool use_dts, u64 dts, Bool use_pts, u64 cts, u32 au_length){ u32 pes_len; u32 pes_header_data_length; pes_header_data_length = 10; gf_bs_write_int(bs, 0x1, 24);//packet start code gf_bs_write_u8(bs, stream->mpeg2_stream_id);// stream id pes_len = au_length + 3; // 3 = header size if (use_dts) pes_len += 5; if (use_pts) pes_len += 5; gf_bs_write_int(bs, pes_len, 16); // pes packet length gf_bs_write_int(bs, 0x2, 2); // reserved gf_bs_write_int(bs, 0x0, 2); // scrambling gf_bs_write_int(bs, 0x0, 1); // priority gf_bs_write_int(bs, 0x1, 1); // alignment indicator gf_bs_write_int(bs, 0x0, 1); // copyright gf_bs_write_int(bs, 0x0, 1); // original or copy gf_bs_write_int(bs, use_pts, 1); gf_bs_write_int(bs, use_dts, 1); gf_bs_write_int(bs, 0x0, 6); //6 flags = 0 (ESCR, ES_rate, DSM_trick, additional_copy, PES_CRC, PES_extension) gf_bs_write_int(bs, pes_header_data_length, 8); if (use_pts) { u64 t; gf_bs_write_int(bs, use_dts ? 0x3 : 0x2, 4); // reserved '0011' || '0010' t = ((cts >> 30) & 0x7); gf_bs_write_long_int(bs, t, 3); gf_bs_write_int(bs, 1, 1); // marker bit t = ((cts >> 15) & 0x7fff); gf_bs_write_long_int(bs, t, 15); gf_bs_write_int(bs, 1, 1); // marker bit t = cts & 0x7fff; gf_bs_write_long_int(bs, t, 15); gf_bs_write_int(bs, 1, 1); // marker bit } if (use_dts) { u64 t; gf_bs_write_int(bs, 0x1, 4); // reserved '0001' t = ((dts >> 30) & 0x7); gf_bs_write_long_int(bs, t, 3); gf_bs_write_int(bs, 1, 1); // marker bit t = ((dts >> 15) & 0x7fff); gf_bs_write_long_int(bs, t, 15); gf_bs_write_int(bs, 1, 1); // marker bit t = dts & 0x7fff; gf_bs_write_long_int(bs, t, 15); gf_bs_write_int(bs, 1, 1); // marker bit } return pes_len+4; // 4 = start code + stream_id}void m2ts_mux_pes_get_next_packet(M2TS_Mux_Stream *stream, u8 *packet){ GF_BitStream *bs; Bool au_start, is_rap, needs_pcr; u32 remain, adaptation_field_control, payload_length, padding_length; assert(stream->pid); bs = gf_bs_new(packet, 188, GF_BITSTREAM_WRITE); au_start = 0; if (!stream->pck_offset && (stream->pck.flags & GF_ESI_DATA_AU_START) ) au_start = 1; remain = stream->pck.data_len - stream->pck_offset; adaptation_field_control = M2TS_ADAPTATION_NONE; payload_length = 184 - PES_HEADER_LENGTH*au_start; needs_pcr = (au_start && (stream==stream->program->pcr) ) ? 1 : 0; padding_length = 0; if (needs_pcr) { adaptation_field_control = M2TS_ADAPTATION_AND_PAYLOAD; /*AF headers + PCR*/ payload_length -= 8; } else if (remain<184) { /*AF headers*/ payload_length -= 2; adaptation_field_control = M2TS_ADAPTATION_AND_PAYLOAD; } if (remain>=payload_length) { padding_length = 0; } else { padding_length = payload_length - remain; payload_length -= padding_length; } gf_bs_write_int(bs, 0x47, 8); // sync byte gf_bs_write_int(bs, 0, 1); // error indicator gf_bs_write_int(bs, au_start, 1); // start ind gf_bs_write_int(bs, 0, 1); // transport priority gf_bs_write_int(bs, stream->pid, 13); // pid gf_bs_write_int(bs, 0, 2); // scrambling gf_bs_write_int(bs, adaptation_field_control, 2); // we do not use adaptation field for sections gf_bs_write_int(bs, stream->continuity_counter, 4); // continuity counter if (stream->continuity_counter < 15) stream->continuity_counter++; else stream->continuity_counter=0; if (au_start && (stream->pck.flags & GF_ESI_DATA_AU_RAP) ) is_rap = 1; else is_rap = 0; if (adaptation_field_control != M2TS_ADAPTATION_NONE) { /*FIXME - WE NEED A REAL PCR, NOT THE DTS*/ m2ts_add_adaptation(bs, needs_pcr, stream->pck.dts, is_rap, padding_length); } /*FIXME - we need proper packetization here in case we're not fed with full AUs*/ if (au_start) { m2ts_stream_add_pes_header(bs, stream, (stream->ifce->caps & GF_ESI_SIGNAL_DTS) ? 1 : 0, stream->pck.dts, 1, stream->pck.cts, stream->pck.data_len); } gf_bs_del(bs); memcpy(packet+188-payload_length, stream->pck.data + stream->pck_offset, payload_length); stream->pck_offset += payload_length; assert(stream->pck_offset <= stream->pck.data_len); m2ts_time_inc(&stream->time, payload_length, stream->bit_rate);}M2TS_Mux_Stream *m2ts_stream_new(u32 pid) { M2TS_Mux_Stream *stream; GF_SAFEALLOC(stream, M2TS_Mux_Stream); stream->pid = pid; stream->process = m2ts_stream_process_stream; return stream;}GF_Err m2ts_output_ctrl(GF_ESInterface *_self, u32 ctrl_type, void *param){ GF_ESIPacket *esi_pck; M2TS_Packet *pck; M2TS_Mux_Stream *stream = (M2TS_Mux_Stream *)_self->output_udta; switch (ctrl_type) { case GF_ESI_OUTPUT_DATA_DISPATCH: GF_SAFEALLOC(pck, M2TS_Packet); esi_pck = (GF_ESIPacket *)param; pck->data_len = esi_pck->data_len; pck->data = malloc(sizeof(char)*pck->data_len); memcpy(pck->data, esi_pck->data, pck->data_len); pck->flags = esi_pck->flags; pck->cts = esi_pck->cts; pck->dts = esi_pck->dts; gf_mx_p(stream->mx); if (!stream->pck_first) { stream->pck_first = stream->pck_last = pck; } else { stream->pck_last->next = pck; stream->pck_last = pck; } gf_mx_v(stream->mx); break; } return GF_OK;}M2TS_Mux_Stream *m2ts_program_stream_add(M2TS_Mux_Program *program, struct __elementary_stream_ifce *ifce, u32 pid, Bool is_pcr){ M2TS_Mux_Stream *stream, *st; stream = m2ts_stream_new(pid); stream->ifce = ifce; stream->pid = pid; stream->program = program; if (is_pcr) program->pcr = stream; if (program->streams) { st = program->streams; while (st->next) st = st->next; st->next = stream; } else { program->streams = stream; } if (program->pmt) program->pmt->table_needs_update = 1; stream->bit_rate = ifce->bit_rate; switch (ifce->stream_type) { case GF_STREAM_VISUAL: switch (ifce->object_type_indication) { case 0x20: stream->mpeg2_stream_type = GF_M2TS_VIDEO_MPEG4; break; case 0x21: stream->mpeg2_stream_type = GF_M2TS_VIDEO_H264; break; case 0x6A: stream->mpeg2_stream_type = GF_M2TS_VIDEO_MPEG1; break; case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: stream->mpeg2_stream_type = GF_M2TS_VIDEO_MPEG2; break; default: break; } /*just pick first valid stream_id in visual range*/ stream->mpeg2_stream_id = 0xE0; break; case GF_STREAM_AUDIO: switch (ifce->object_type_indication) { case 0x6B: stream->mpeg2_stream_type = GF_M2TS_AUDIO_MPEG1; break; case 0x69: stream->mpeg2_stream_type = GF_M2TS_AUDIO_MPEG2; break; case 0x40: stream->mpeg2_stream_type = GF_M2TS_AUDIO_AAC; break; } /*just pick first valid stream_id in audio range*/ stream->mpeg2_stream_id = 0xC0; break; } stream->ifce->output_ctrl = m2ts_output_ctrl; stream->ifce->output_udta = stream; stream->mx = gf_mx_new(); if (ifce->timescale != 90000) stream->ts_scale = 90000.0 / ifce->timescale; return stream;}#define M2TS_PSI_REFRESH_RATE 200M2TS_Mux_Program *m2ts_mux_program_add(M2TS_Mux *muxer, u32 program_number, u32 pmt_pid){ M2TS_Mux_Program *program; GF_SAFEALLOC(program, M2TS_Mux_Program); program->mux = muxer; program->number = program_number; if (muxer->programs) { M2TS_Mux_Program *p = muxer->programs; while (p->next) p = p->next; p->next = program; } else { muxer->programs = program; } program->pmt = m2ts_stream_new(pmt_pid); program->pmt->program = program; muxer->pat->table_needs_update = 1; program->pmt->process = m2ts_stream_process_pmt; program->pmt->refresh_rate_ms = M2TS_PSI_REFRESH_RATE; return program;}M2TS_Mux *m2ts_mux_new(u32 mux_rate, Bool real_time){ GF_BitStream *bs; M2TS_Mux *muxer; GF_SAFEALLOC(muxer, M2TS_Mux); muxer->pat = m2ts_stream_new(0); /* 0 = PAT_PID */ muxer->pat->process = m2ts_stream_process_pat; muxer->pat->refresh_rate_ms = M2TS_PSI_REFRESH_RATE; muxer->real_time = real_time; muxer->bit_rate = mux_rate; if (mux_rate) muxer->fixed_rate = 1; /*format NULL packet*/ bs = gf_bs_new(muxer->null_pck, 188, GF_BITSTREAM_WRITE); gf_bs_write_int(bs, 0x47, 8); gf_bs_write_int(bs, 0, 1); gf_bs_write_int(bs, 0, 1); gf_bs_write_int(bs, 0, 1); gf_bs_write_int(bs, 0x1FFF, 13); gf_bs_write_int(bs, 0, 2); gf_bs_write_int(bs, 1, 2); gf_bs_write_int(bs, 0, 4); gf_bs_del(bs); return muxer;}void m2ts_mux_stream_del(M2TS_Mux_Stream *st){ while (st->tables) { M2TS_Mux_Table *tab = st->tables->next; while (st->tables->section) { M2TS_Mux_Section *sec = st->tables->section->next; free(st->tables->section->data); free(st->tables->section); st->tables->section = sec; } free(st->tables); st->tables = tab; } while (st->pck_first) { M2TS_Packet *pck = st->pck_first; st->pck_first = pck->next; free(pck->data); free(pck); } if (st->mx) gf_mx_del(st->mx); free(st);}void m2ts_mux_program_del(M2TS_Mux_Program *prog){ while (prog->streams) { M2TS_Mux_Stream *st = prog->streams->next; m2ts_mux_stream_del(prog->streams); prog->streams = st; } m2ts_mux_stream_del(prog->pmt); free(prog);}void m2ts_mux_del(M2TS_Mux *mux){ while (mux->programs) { M2TS_Mux_Program *p = mux->programs->next; m2ts_mux_program_del(mux->programs); mux->programs = p; } m2ts_mux_stream_del(mux->pat); free(mux);}void m2ts_mux_update_config(M2TS_Mux *mux, Bool reset_time){ M2TS_Mux_Program *prog; if (!mux->fixed_rate) { mux->bit_rate = 0; /*get PAT bitrate*/ m2ts_mux_table_update_bitrate(mux, mux->pat); mux->bit_rate += mux->pat->bit_rate; } prog = mux->programs; while (prog) { M2TS_Mux_Stream *stream = prog->streams; while (stream) { /*!! WATCHOUT - this is raw bitrate without PES header overhead !!*/ if (!mux->fixed_rate) { mux->bit_rate += stream->bit_rate; /*update PCR every 100ms - we need at least 8 bytes without padding*/ if (stream == prog->pcr) mux->bit_rate += 8*8*10; } /*reset mux time*/ if (reset_time) stream->time.sec = stream->time.nanosec = 0; stream = stream->next; } /*get PMT bitrate*/ if (!mux->fixed_rate) { m2ts_mux_table_update_bitrate(mux, prog->pmt); mux->bit_rate += prog->pmt->bit_rate; } prog = prog->next; } /*reset mux time*/ if (reset_time) { mux->time.sec = mux->time.nanosec = 0; mux->init_sys_time = 0; }}u32 gf_m2ts_get_sys_clock(M2TS_Mux *muxer){ return gf_sys_clock() - muxer->init_sys_time;}u32 gf_m2ts_get_ts_clock(M2TS_Mux *muxer){ u32 now, init; init = muxer->init_ts_time.sec*1000 + muxer->init_ts_time.nanosec/1000000; now = muxer->time.sec*1000 + muxer->time.nanosec/1000000; return now-init;}const char *m2ts_mux_process(M2TS_Mux *muxer, u32 *status){ M2TS_Mux_Program *program; M2TS_Mux_Stream *stream, *stream_to_process; M2TS_Time time; u32 now, nb_streams, nb_streams_done; char *ret; Bool res; nb_streams = nb_streams_done = 0; *status = GF_M2TS_STATE_IDLE; now = gf_sys_clock(); if (muxer->real_time) { if (!muxer->init_sys_time) { muxer->init_sys_time = now; muxer->init_ts_time = muxer->time; } else { u32 diff = now - muxer->init_sys_time; M2TS_Time now = muxer->init_ts_time; m2ts_time_inc(&now, diff, 1000); if (m2ts_time_less(&now, &muxer->time)) return NULL; } } stream_to_process = NULL; time = muxer->time; if (muxer->needs_reconfig) { m2ts_mux_update_config(muxer, 0); muxer->needs_reconfig = 0; } res = muxer->pat->process(muxer, muxer->pat); if (res && m2ts_time_less_or_equal(&muxer->pat->time, &time) ) { time = muxer->pat->time; stream_to_process = muxer->pat; /*force sending the PAT regardless of other streams*/ goto send_pck; } program = muxer->programs; while (program) { res = program->pmt->process(muxer, program->pmt); if (res && m2ts_time_less(&program->pmt->time, &time) ) { time = program->pmt->time; stream_to_process = program->pmt; /*force sending the PMT regardless of other streams*/ goto send_pck; } stream = program->streams; while (stream) { nb_streams ++; res = stream->process(muxer, stream); if (res) { if (m2ts_time_less(&stream->time, &time)) { time = stream->time; stream_to_process = stream; } } else { if (stream->ifce->caps & GF_ESI_STREAM_IS_OVER) nb_streams_done ++; } stream = stream->next; } program = program->next; }send_pck: ret = NULL; if (!stream_to_process) { if (nb_streams && (nb_streams==nb_streams_done)) { *status = GF_M2TS_STATE_EOS; } else { /* padding packets ?? */ if (muxer->fixed_rate) { GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Inserting empty packet at %d:%d\n", time.sec, time.nanosec)); ret = muxer->null_pck; } /*we still need to increase the mux time, even though we're not fixed-rate*/ else { m2ts_time_inc(&muxer->time, 1504/*188*8*/, muxer->bit_rate); } *status = GF_M2TS_STATE_PADDING; } } else { if (stream_to_process->tables) { m2ts_mux_table_get_next_packet(stream_to_process, muxer->dst_pck); GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Sending table packet from PID %d at %d:%d\n", stream_to_process->pid, time.sec, time.nanosec)); } else { m2ts_mux_pes_get_next_packet(stream_to_process, muxer->dst_pck); GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[MPEG2-TS Muxer] Sending PES packet from PID %d at %d:%d\n", stream_to_process->pid, time.sec, time.nanosec)); } ret = muxer->dst_pck; *status = GF_M2TS_STATE_DATA; } if (ret) { muxer->tot_pck_sent++; /*increment time*/ m2ts_time_inc(&muxer->time, 1504/*188*8*/, muxer->bit_rate); muxer->pck_sent++; if (now - muxer->last_br_time > 500) { u64 size = 8*188*muxer->pck_sent*1000; muxer->avg_br = (u32) (size/(now - muxer->last_br_time));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -