📄 mpeg.c
字号:
if (s->is_vcd || s->is_mpeg2) /* every packet */ s->pack_header_freq = 1; else /* every 2 seconds */ s->pack_header_freq = 2 * bitrate / s->packet_size / 8; /* the above seems to make pack_header_freq zero sometimes */ if (s->pack_header_freq == 0) s->pack_header_freq = 1; if (s->is_mpeg2) /* every 200 packets. Need to look at the spec. */ s->system_header_freq = s->pack_header_freq * 40; else if (s->is_vcd) /* the standard mandates that there are only two system headers in the whole file: one in the first packet of each stream. (see standard p. IV-7 and IV-8) */ s->system_header_freq = 0x7fffffff; else s->system_header_freq = s->pack_header_freq * 5; for(i=0;i<ctx->nb_streams;i++) { stream = ctx->streams[i]->priv_data; stream->buffer_ptr = 0; stream->packet_number = 0; stream->start_pts = AV_NOPTS_VALUE; stream->start_dts = AV_NOPTS_VALUE; } s->system_header_size = get_system_header_size(ctx); s->last_scr = 0; return 0; fail: for(i=0;i<ctx->nb_streams;i++) { av_free(ctx->streams[i]->priv_data); } return -ENOMEM;}static inline void put_timestamp(ByteIOContext *pb, int id, int64_t timestamp){ put_byte(pb, (id << 4) | (((timestamp >> 30) & 0x07) << 1) | 1); put_be16(pb, (uint16_t)((((timestamp >> 15) & 0x7fff) << 1) | 1)); put_be16(pb, (uint16_t)((((timestamp) & 0x7fff) << 1) | 1));}/* return the number of padding bytes that should be inserted into the multiplexed stream.*/static int get_vcd_padding_size(AVFormatContext *ctx, int64_t pts){ MpegMuxContext *s = ctx->priv_data; int pad_bytes = 0; if (s->vcd_padding_bitrate > 0 && pts!=AV_NOPTS_VALUE) { int64_t full_pad_bytes; full_pad_bytes = (int64_t)((s->vcd_padding_bitrate * (pts / 90000.0)) / 8.0); pad_bytes = (int) (full_pad_bytes - s->vcd_padding_bytes_written); if (pad_bytes<0) /* might happen if we have already padded to a later timestamp. This can occur if another stream has already advanced further.*/ pad_bytes=0; } return pad_bytes;}/* return the exact available payload size for the next packet for stream 'stream_index'. 'pts' and 'dts' are only used to know if timestamps are needed in the packet header. */static int get_packet_payload_size(AVFormatContext *ctx, int stream_index, int64_t pts, int64_t dts){ MpegMuxContext *s = ctx->priv_data; int buf_index; StreamInfo *stream; stream = ctx->streams[stream_index]->priv_data; buf_index = 0; if (((s->packet_number % s->pack_header_freq) == 0)) { /* pack header size */ if (s->is_mpeg2) buf_index += 14; else buf_index += 12; if (s->is_vcd) { /* there is exactly one system header for each stream in a VCD MPEG, One in the very first video packet and one in the very first audio packet (see VCD standard p. IV-7 and IV-8).*/ if (stream->packet_number==0) /* The system headers refer only to the stream they occur in, so they have a constant size.*/ buf_index += 15; } else { if ((s->packet_number % s->system_header_freq) == 0) buf_index += s->system_header_size; } } if ((s->is_vcd && stream->packet_number==0) || (s->is_svcd && s->packet_number==0)) /* the first pack of each stream contains only the pack header, the system header and some padding (see VCD standard p. IV-6) Add the padding size, so that the actual payload becomes 0.*/ buf_index += s->packet_size - buf_index; else { /* packet header size */ buf_index += 6; if (s->is_mpeg2) { buf_index += 3; if (stream->packet_number==0) buf_index += 3; /* PES extension */ buf_index += 1; /* obligatory stuffing byte */ } if (pts != AV_NOPTS_VALUE) { if (dts != pts) buf_index += 5 + 5; else buf_index += 5; } else { if (!s->is_mpeg2) buf_index++; } if (stream->id < 0xc0) { /* AC3/LPCM private data header */ buf_index += 4; if (stream->id >= 0xa0) { int n; buf_index += 3; /* NOTE: we round the payload size to an integer number of LPCM samples */ n = (s->packet_size - buf_index) % stream->lpcm_align; if (n) buf_index += (stream->lpcm_align - n); } } if (s->is_vcd && stream->id == AUDIO_ID) /* The VCD standard demands that 20 zero bytes follow each audio packet (see standard p. IV-8).*/ buf_index+=20; } return s->packet_size - buf_index; }/* Write an MPEG padding packet header. */static int put_padding_header(AVFormatContext *ctx,uint8_t* buf, int full_padding_size){ MpegMuxContext *s = ctx->priv_data; int size = full_padding_size - 6; /* subtract header length */ buf[0] = (uint8_t)(PADDING_STREAM >> 24); buf[1] = (uint8_t)(PADDING_STREAM >> 16); buf[2] = (uint8_t)(PADDING_STREAM >> 8); buf[3] = (uint8_t)(PADDING_STREAM); buf[4] = (uint8_t)(size >> 8); buf[5] = (uint8_t)(size & 0xff); if (!s->is_mpeg2) { buf[6] = 0x0f; return 7; } else return 6;}static void put_padding_packet(AVFormatContext *ctx, ByteIOContext *pb,int packet_bytes){ uint8_t buffer[7]; int size, i; size = put_padding_header(ctx,buffer, packet_bytes); put_buffer(pb, buffer, size); packet_bytes -= size; for(i=0;i<packet_bytes;i++) put_byte(pb, 0xff);}/* flush the packet on stream stream_index */static void flush_packet(AVFormatContext *ctx, int stream_index, int64_t pts, int64_t dts, int64_t scr){ MpegMuxContext *s = ctx->priv_data; StreamInfo *stream = ctx->streams[stream_index]->priv_data; uint8_t *buf_ptr; int size, payload_size, startcode, id, stuffing_size, i, header_len; int packet_size; uint8_t buffer[128]; int zero_trail_bytes = 0; int pad_packet_bytes = 0; int pes_flags; int general_pack = 0; /*"general" pack without data specific to one stream?*/ id = stream->id; #if 0 printf("packet ID=%2x PTS=%0.3f\n", id, pts / 90000.0);#endif buf_ptr = buffer; if (((s->packet_number % s->pack_header_freq) == 0)) { /* output pack and systems header if needed */ size = put_pack_header(ctx, buf_ptr, scr); buf_ptr += size; if (s->is_vcd) { /* there is exactly one system header for each stream in a VCD MPEG, One in the very first video packet and one in the very first audio packet (see VCD standard p. IV-7 and IV-8).*/ if (stream->packet_number==0) { size = put_system_header(ctx, buf_ptr, id); buf_ptr += size; } } else { if ((s->packet_number % s->system_header_freq) == 0) { size = put_system_header(ctx, buf_ptr, 0); buf_ptr += size; } } } size = buf_ptr - buffer; put_buffer(&ctx->pb, buffer, size); packet_size = s->packet_size - size; if (s->is_vcd && id == AUDIO_ID) /* The VCD standard demands that 20 zero bytes follow each audio pack (see standard p. IV-8).*/ zero_trail_bytes += 20; if ((s->is_vcd && stream->packet_number==0) || (s->is_svcd && s->packet_number==0)) { /* for VCD the first pack of each stream contains only the pack header, the system header and lots of padding (see VCD standard p. IV-6). In the case of an audio pack, 20 zero bytes are also added at the end.*/ /* For SVCD we fill the very first pack to increase compatibility with some DVD players. Not mandated by the standard.*/ if (s->is_svcd) general_pack = 1; /* the system header refers to both streams and no stream data*/ pad_packet_bytes = packet_size - zero_trail_bytes; } packet_size -= pad_packet_bytes + zero_trail_bytes; if (packet_size > 0) { /* packet header size */ packet_size -= 6; /* packet header */ if (s->is_mpeg2) { header_len = 3; if (stream->packet_number==0) header_len += 3; /* PES extension */ header_len += 1; /* obligatory stuffing byte */ } else { header_len = 0; } if (pts != AV_NOPTS_VALUE) { if (dts != pts) header_len += 5 + 5; else header_len += 5; } else { if (!s->is_mpeg2) header_len++; } payload_size = packet_size - header_len; if (id < 0xc0) { startcode = PRIVATE_STREAM_1; payload_size -= 4; if (id >= 0xa0) payload_size -= 3; } else { startcode = 0x100 + id; } stuffing_size = payload_size - stream->buffer_ptr; if (stuffing_size < 0) stuffing_size = 0; if (stuffing_size > 16) { /*<=16 for MPEG-1, <=32 for MPEG-2*/ pad_packet_bytes += stuffing_size; packet_size -= stuffing_size; payload_size -= stuffing_size; stuffing_size = 0; } put_be32(&ctx->pb, startcode); put_be16(&ctx->pb, packet_size); if (!s->is_mpeg2) for(i=0;i<stuffing_size;i++) put_byte(&ctx->pb, 0xff); if (s->is_mpeg2) { put_byte(&ctx->pb, 0x80); /* mpeg2 id */ pes_flags=0; if (pts != AV_NOPTS_VALUE) { pes_flags |= 0x80; if (dts != pts) pes_flags |= 0x40; } /* Both the MPEG-2 and the SVCD standards demand that the P-STD_buffer_size field be included in the first packet of every stream. (see SVCD standard p. 26 V.2.3.1 and V.2.3.2 and MPEG-2 standard 2.7.7) */ if (stream->packet_number == 0) pes_flags |= 0x01; put_byte(&ctx->pb, pes_flags); /* flags */ put_byte(&ctx->pb, header_len - 3 + stuffing_size); if (pes_flags & 0x80) /*write pts*/ put_timestamp(&ctx->pb, (pes_flags & 0x40) ? 0x03 : 0x02, pts); if (pes_flags & 0x40) /*write dts*/ put_timestamp(&ctx->pb, 0x01, dts); if (pes_flags & 0x01) { /*write pes extension*/ put_byte(&ctx->pb, 0x10); /* flags */ /* P-STD buffer info */ if (id == AUDIO_ID) put_be16(&ctx->pb, 0x4000 | stream->max_buffer_size/128); else put_be16(&ctx->pb, 0x6000 | stream->max_buffer_size/1024); } } else { if (pts != AV_NOPTS_VALUE) { if (dts != pts) { put_timestamp(&ctx->pb, 0x03, pts); put_timestamp(&ctx->pb, 0x01, dts); } else { put_timestamp(&ctx->pb, 0x02, pts); } } else { put_byte(&ctx->pb, 0x0f); } } if (s->is_mpeg2) { /* special stuffing byte that is always written to prevent accidental generation of start codes. */ put_byte(&ctx->pb, 0xff); for(i=0;i<stuffing_size;i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -