📄 mpegtsenc.c.svn-base
字号:
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; const char *service_name; ts->tsid = DEFAULT_TSID; ts->onid = DEFAULT_ONID; /* allocate a single DVB service */ service_name = s->title; if (service_name[0] == '\0') service_name = DEFAULT_SERVICE_NAME; service = mpegts_add_service(ts, DEFAULT_SID, DEFAULT_PROVIDER_NAME, 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->service = service; ts_st->pid = DEFAULT_START_PID + i; ts_st->payload_pts = AV_NOPTS_VALUE; ts_st->payload_dts = AV_NOPTS_VALUE; /* update PCR pid by using the first video stream */ 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 no video stream, use the first stream as PCR */ if (service->pcr_pid == 0x1fff && s->nb_streams > 0) { ts_st = s->streams[0]->priv_data; service->pcr_pid = ts_st->pid; } if (total_bit_rate <= 8 * 1024) total_bit_rate = 8 * 1024; service->pcr_packet_freq = (total_bit_rate * PCR_RETRANS_TIME) / (TS_PACKET_SIZE * 8 * 1000); 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]); } }}static void write_pts(uint8_t *q, int fourbits, int64_t pts){ int val; val = fourbits << 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;}/* 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, int64_t dts){ MpegTSWriteStream *ts_st = st->priv_data; uint8_t buf[TS_PACKET_SIZE]; uint8_t *q; int val, is_start, len, header_len, write_pcr, private_code, flags; int afc_len, stuffing_len; int64_t pcr = -1; /* avoid warning */ is_start = 1; while (payload_size > 0) { retransmit_si_info(s); write_pcr = 0; if (ts_st->pid == ts_st->service->pcr_pid) { ts_st->service->pcr_packet_count++; if (ts_st->service->pcr_packet_count >= ts_st->service->pcr_packet_freq) { ts_st->service->pcr_packet_count = 0; write_pcr = 1; /* XXX: this is incorrect, but at least we have a PCR value */ pcr = pts; } } /* 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 | (write_pcr ? 0x20 : 0); ts_st->cc = (ts_st->cc + 1) & 0xf; if (write_pcr) { *q++ = 7; /* AFC length */ *q++ = 0x10; /* flags: PCR present */ *q++ = pcr >> 25; *q++ = pcr >> 17; *q++ = pcr >> 9; *q++ = pcr >> 1; *q++ = (pcr & 1) << 7; *q++ = 0; } if (is_start) { /* write PES header */ *q++ = 0x00; *q++ = 0x00; *q++ = 0x01; private_code = 0; if (st->codec->codec_type == CODEC_TYPE_VIDEO) { *q++ = 0xe0; } else if (st->codec->codec_type == CODEC_TYPE_AUDIO && (st->codec->codec_id == CODEC_ID_MP2 || st->codec->codec_id == CODEC_ID_MP3)) { *q++ = 0xc0; } else { *q++ = 0xbd; if (st->codec->codec_type == CODEC_TYPE_SUBTITLE) { private_code = 0x20; } } header_len = 0; flags = 0; if (pts != AV_NOPTS_VALUE) { header_len += 5; flags |= 0x80; } if (dts != AV_NOPTS_VALUE) { header_len += 5; flags |= 0x40; } len = payload_size + header_len + 3; if (private_code != 0) len++; *q++ = len >> 8; *q++ = len; val = 0x80; /* data alignment indicator is required for subtitle data */ if (st->codec->codec_type == CODEC_TYPE_SUBTITLE) val |= 0x04; *q++ = val; *q++ = flags; *q++ = header_len; if (pts != AV_NOPTS_VALUE) { write_pts(q, flags >> 6, pts); q += 5; } if (dts != AV_NOPTS_VALUE) { write_pts(q, 1, dts); q += 5; } if (private_code != 0) *q++ = private_code; is_start = 0; } /* header size */ header_len = q - buf; /* data len */ len = TS_PACKET_SIZE - header_len; if (len > payload_size) len = payload_size; stuffing_len = TS_PACKET_SIZE - header_len - len; if (stuffing_len > 0) { /* add stuffing with AFC */ if (buf[3] & 0x20) { /* stuffing already present: increase its size */ afc_len = buf[4] + 1; memmove(buf + 4 + afc_len + stuffing_len, buf + 4 + afc_len, header_len - (4 + afc_len)); buf[4] += stuffing_len; memset(buf + 4 + afc_len, 0xff, stuffing_len); } else { /* add stuffing */ memmove(buf + 4 + stuffing_len, buf + 4, header_len - 4); buf[3] |= 0x20; buf[4] = stuffing_len - 1; if (stuffing_len >= 2) { buf[5] = 0x00; memset(buf + 6, 0xff, stuffing_len - 2); } } } memcpy(buf + TS_PACKET_SIZE - len, payload, len); payload += len; payload_size -= len; put_buffer(s->pb, buf, TS_PACKET_SIZE); } put_flush_packet(s->pb);}static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt){ AVStream *st = s->streams[pkt->stream_index]; int size= pkt->size; uint8_t *buf= pkt->data; MpegTSWriteStream *ts_st = st->priv_data; int len, max_payload_size; if (st->codec->codec_type == CODEC_TYPE_SUBTITLE) { /* for subtitle, a single PES packet must be generated */ mpegts_write_pes(s, st, buf, size, pkt->pts, AV_NOPTS_VALUE); return 0; } max_payload_size = DEFAULT_PES_PAYLOAD_SIZE; while (size > 0) { len = max_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 = pkt->pts; if (ts_st->payload_dts == AV_NOPTS_VALUE) ts_st->payload_dts = pkt->dts; if (ts_st->payload_index >= max_payload_size) { mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index, ts_st->payload_pts, ts_st->payload_dts); ts_st->payload_pts = AV_NOPTS_VALUE; ts_st->payload_dts = 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, ts_st->payload_dts); } } 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); return 0;}AVOutputFormat mpegts_muxer = { "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,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -