📄 mpegtsenc.c
字号:
MpegTSService *service; uint8_t data[1012], *q, *desc_list_len_ptr, *desc_len_ptr; int i, running_status, free_ca_mode, val; q = data; put16(&q, ts->onid); *q++ = 0xff; for(i = 0; i < ts->nb_services; i++) { service = ts->services[i]; put16(&q, service->sid); *q++ = 0xfc | 0x00; /* currently no EIT info */ desc_list_len_ptr = q; q += 2; running_status = 4; /* running */ free_ca_mode = 0; /* write only one descriptor for the service name and provider */ *q++ = 0x48; desc_len_ptr = q; q++; *q++ = 0x01; /* digital television service */ putstr8(&q, service->provider_name); putstr8(&q, service->name); desc_len_ptr[0] = q - desc_len_ptr - 1; /* fill descriptor length */ val = (running_status << 13) | (free_ca_mode << 12) | (q - desc_list_len_ptr - 2); desc_list_len_ptr[0] = val >> 8; desc_list_len_ptr[1] = val; } mpegts_write_section1(&ts->sdt, SDT_TID, ts->tsid, 0, 0, 0, data, q - data);}static MpegTSService *mpegts_add_service(MpegTSWrite *ts, int sid, const char *provider_name, const char *name){ MpegTSService *service; service = av_mallocz(sizeof(MpegTSService)); if (!service) return NULL; service->pmt.pid = DEFAULT_PMT_START_PID + ts->nb_services - 1; service->sid = sid; service->provider_name = av_strdup(provider_name); service->name = av_strdup(name); service->pcr_pid = 0x1fff; dynarray_add(&ts->services, &ts->nb_services, service); return service;}static void section_write_packet(MpegTSSection *s, const uint8_t *packet){ AVFormatContext *ctx = s->opaque; put_buffer(&ctx->pb, packet, TS_PACKET_SIZE);}static int mpegts_write_header(AVFormatContext *s){ MpegTSWrite *ts = s->priv_data; MpegTSWriteStream *ts_st; MpegTSService *service; AVStream *st; int i, total_bit_rate; ts->tsid = DEFAULT_TSID; ts->onid = DEFAULT_ONID; /* allocate a single DVB service */ service = mpegts_add_service(ts, DEFAULT_SID, DEFAULT_PROVIDER_NAME, DEFAULT_SERVICE_NAME); service->pmt.write_packet = section_write_packet; service->pmt.opaque = s; ts->pat.pid = PAT_PID; ts->pat.cc = 0; ts->pat.write_packet = section_write_packet; ts->pat.opaque = s; ts->sdt.pid = SDT_PID; ts->sdt.cc = 0; ts->sdt.write_packet = section_write_packet; ts->sdt.opaque = s; /* assign pids to each stream */ total_bit_rate = 0; for(i = 0;i < s->nb_streams; i++) { st = s->streams[i]; ts_st = av_mallocz(sizeof(MpegTSWriteStream)); if (!ts_st) goto fail; st->priv_data = ts_st; ts_st->pid = DEFAULT_START_PID + i; ts_st->payload_pts = AV_NOPTS_VALUE; /* update PCR pid if needed */ if (st->codec.codec_type == CODEC_TYPE_VIDEO && service->pcr_pid == 0x1fff) service->pcr_pid = ts_st->pid; total_bit_rate += st->codec.bit_rate; } if (total_bit_rate <= 8 * 1024) total_bit_rate = 8 * 1024; ts->sdt_packet_freq = (total_bit_rate * SDT_RETRANS_TIME) / (TS_PACKET_SIZE * 8 * 1000); ts->pat_packet_freq = (total_bit_rate * PAT_RETRANS_TIME) / (TS_PACKET_SIZE * 8 * 1000);#if 0 printf("%d %d %d\n", total_bit_rate, ts->sdt_packet_freq, ts->pat_packet_freq);#endif /* write info at the start of the file, so that it will be fast to find them */ mpegts_write_sdt(s); mpegts_write_pat(s); for(i = 0; i < ts->nb_services; i++) { mpegts_write_pmt(s, ts->services[i]); } put_flush_packet(&s->pb); return 0; fail: for(i = 0;i < s->nb_streams; i++) { st = s->streams[i]; av_free(st->priv_data); } return -1;}/* send SDT, PAT and PMT tables regulary */static void retransmit_si_info(AVFormatContext *s){ MpegTSWrite *ts = s->priv_data; int i; if (++ts->sdt_packet_count == ts->sdt_packet_freq) { ts->sdt_packet_count = 0; mpegts_write_sdt(s); } if (++ts->pat_packet_count == ts->pat_packet_freq) { ts->pat_packet_count = 0; mpegts_write_pat(s); for(i = 0; i < ts->nb_services; i++) { mpegts_write_pmt(s, ts->services[i]); } }}/* NOTE: pes_data contains all the PES packet */static void mpegts_write_pes(AVFormatContext *s, AVStream *st, const uint8_t *payload, int payload_size, int64_t pts){ MpegTSWriteStream *ts_st = st->priv_data; uint8_t buf[TS_PACKET_SIZE]; uint8_t *q; int val, is_start, len, ts_len, header_len; is_start = 1; while (payload_size > 0) { retransmit_si_info(s); /* prepare packet header */ q = buf; *q++ = 0x47; val = (ts_st->pid >> 8); if (is_start) val |= 0x40; *q++ = val; *q++ = ts_st->pid; *q++ = 0x10 | ts_st->cc; ts_st->cc = (ts_st->cc + 1) & 0xf; if (is_start) { /* write PES header */ *q++ = 0x00; *q++ = 0x00; *q++ = 0x01; if (st->codec.codec_type == CODEC_TYPE_VIDEO) *q++ = 0xe0; else *q++ = 0xc0; if (pts != AV_NOPTS_VALUE) header_len = 8; else header_len = 3; len = payload_size + header_len; *q++ = len >> 8; *q++ = len; *q++ = 0x80; if (pts != AV_NOPTS_VALUE) { *q++ = 0x80; /* PTS only */ *q++ = 0x05; /* header len */ val = (0x02 << 4) | (((pts >> 30) & 0x07) << 1) | 1; *q++ = val; val = (((pts >> 15) & 0x7fff) << 1) | 1; *q++ = val >> 8; *q++ = val; val = (((pts) & 0x7fff) << 1) | 1; *q++ = val >> 8; *q++ = val; } else { *q++ = 0x00; *q++ = 0x00; } is_start = 0; } /* write header */ ts_len = q - buf; put_buffer(&s->pb, buf, ts_len); /* write data */ len = TS_PACKET_SIZE - ts_len; if (len > payload_size) len = payload_size; put_buffer(&s->pb, payload, len); payload += len; payload_size -= len; ts_len += len; /* stuffing */ len = TS_PACKET_SIZE - ts_len; if (len > 0) { memset(buf, 0xff, len); put_buffer(&s->pb, buf, len); } } put_flush_packet(&s->pb);}static int mpegts_write_packet(AVFormatContext *s, int stream_index, const uint8_t *buf, int size, int64_t pts1){ AVStream *st = s->streams[stream_index]; MpegTSWriteStream *ts_st = st->priv_data; int len; while (size > 0) { len = DEFAULT_PES_PAYLOAD_SIZE - ts_st->payload_index; if (len > size) len = size; memcpy(ts_st->payload + ts_st->payload_index, buf, len); buf += len; size -= len; ts_st->payload_index += len; if (ts_st->payload_pts == AV_NOPTS_VALUE) ts_st->payload_pts = pts1; if (ts_st->payload_index >= DEFAULT_PES_PAYLOAD_SIZE) { mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index, ts_st->payload_pts); ts_st->payload_pts = AV_NOPTS_VALUE; ts_st->payload_index = 0; } } return 0;}static int mpegts_write_end(AVFormatContext *s){ MpegTSWrite *ts = s->priv_data; MpegTSWriteStream *ts_st; MpegTSService *service; AVStream *st; int i; /* flush current packets */ for(i = 0; i < s->nb_streams; i++) { st = s->streams[i]; ts_st = st->priv_data; if (ts_st->payload_index > 0) { mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index, ts_st->payload_pts); } } put_flush_packet(&s->pb); for(i = 0; i < ts->nb_services; i++) { service = ts->services[i]; av_freep(&service->provider_name); av_freep(&service->name); av_free(service); } av_free(ts->services); for(i = 0; i < s->nb_streams; i++) { st = s->streams[i]; av_free(st->priv_data); } return 0;}AVOutputFormat mpegts_mux = { "mpegts", "MPEG2 transport stream format", "video/x-mpegts", "ts", sizeof(MpegTSWrite), CODEC_ID_MP2, CODEC_ID_MPEG2VIDEO, mpegts_write_header, mpegts_write_packet, mpegts_write_end,};#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -