📄 复件 aviobuf.c
字号:
} \ } while (0)#define DONEBYTES(x) \ do { \ if (header != head_buf) \ buf = header + (x); \ } while (0) if (flags & DEMUX_PAYLOAD_START) goto payload_start; switch (state) { case DEMUX_HEADER: if (state_bytes > 0) { header = head_buf; bytes = state_bytes; goto continue_header; } break; case DEMUX_DATA: if (demux_pid || (state_bytes > end - buf)) { decode_mpeg2 (buf, end); state_bytes -= end - buf; return 0; } decode_mpeg2 (buf, buf + state_bytes); buf += state_bytes; break; case DEMUX_SKIP: if (demux_pid || (state_bytes > end - buf)) { state_bytes -= end - buf; return 0; } buf += state_bytes; break; } while (1) { if (demux_pid) { state = DEMUX_SKIP; return 0; } payload_start: header = buf; bytes = end - buf; continue_header: NEEDBYTES (4); if (header[0] || header[1] || (header[2] != 1)) { if (demux_pid) { state = DEMUX_SKIP; return 0; } else if (header != head_buf) { buf++; goto payload_start; } else { header[0] = header[1]; header[1] = header[2]; header[2] = header[3]; bytes = 3; goto continue_header; } } if (demux_pid) { if ((header[3] >= 0xe0) && (header[3] <= 0xef)) goto pes; fprintf (stderr, "bad stream id %x\n", header[3]); exit (1); } switch (header[3]) { case 0xb9: /* program end code */ /* DONEBYTES (4); */ /* break; */ return 1; case 0xba: /* pack header */ NEEDBYTES (5); if ((header[4] & 0xc0) == 0x40) { /* mpeg2 */ NEEDBYTES (14); len = 14 + (header[13] & 7); NEEDBYTES (len); DONEBYTES (len); /* header points to the mpeg2 pack header */ } else if ((header[4] & 0xf0) == 0x20) { /* mpeg1 */ NEEDBYTES (12); DONEBYTES (12); /* header points to the mpeg1 pack header */ } else { fprintf (stderr, "weird pack header\n"); DONEBYTES (5); } break; default: if (header[3] == demux_track) { pes: NEEDBYTES (7); if ((header[6] & 0xc0) == 0x80) { /* mpeg2 */ NEEDBYTES (9); len = 9 + header[8]; NEEDBYTES (len); /* header points to the mpeg2 pes header */ if (header[7] & 0x80) { uint32_t pts, dts; pts = (((header[9] >> 1) << 30) | (header[10] << 22) | ((header[11] >> 1) << 15) | (header[12] << 7) | (header[13] >> 1)); dts = (!(header[7] & 0x40) ? pts : (((header[14] >> 1) << 30) | (header[15] << 22) | ((header[16] >> 1) << 15) | (header[17] << 7) | (header[18] >> 1)));// mpeg2_tag_picture (mpeg2dec, pts, dts); } } else { /* mpeg1 */ int len_skip; uint8_t * ptsbuf; len = 7; while (header[len - 1] == 0xff) { len++; NEEDBYTES (len); if (len > 23) { fprintf (stderr, "too much stuffing\n"); break; } } if ((header[len - 1] & 0xc0) == 0x40) { len += 2; NEEDBYTES (len); } len_skip = len; len += mpeg1_skip_table[header[len - 1] >> 4]; NEEDBYTES (len); /* header points to the mpeg1 pes header */ ptsbuf = header + len_skip; if ((ptsbuf[-1] & 0xe0) == 0x20) { uint32_t pts, dts; pts = (((ptsbuf[-1] >> 1) << 30) | (ptsbuf[0] << 22) | ((ptsbuf[1] >> 1) << 15) | (ptsbuf[2] << 7) | (ptsbuf[3] >> 1)); dts = (((ptsbuf[-1] & 0xf0) != 0x30) ? pts : (((ptsbuf[4] >> 1) << 30) | (ptsbuf[5] << 22) | ((ptsbuf[6] >> 1) << 15) | (ptsbuf[7] << 7) | (ptsbuf[18] >> 1)));// mpeg2_tag_picture (mpeg2dec, pts, dts); } } DONEBYTES (len); bytes = 6 + (header[4] << 8) + header[5] - len; if (demux_pid || (bytes > end - buf)) { decode_mpeg2 (buf, end); state = DEMUX_DATA; state_bytes = bytes - (end - buf); return 0; } else if (bytes > 0) { decode_mpeg2 (buf, buf + bytes); buf += bytes; } } else if (header[3] < 0xb9) { fprintf (stderr, "looks like a video stream, not system stream\n"); DONEBYTES (4); } else { NEEDBYTES (6); DONEBYTES (6); bytes = (header[4] << 8) + header[5]; if (bytes > end - buf) { state = DEMUX_SKIP; state_bytes = bytes - (end - buf); return 0; } buf += bytes; } } }}//-------------------------------------------------------------------enum MpegTSState { MPEGTS_HEADER = 0, MPEGTS_PESHEADER_FILL, MPEGTS_PAYLOAD, MPEGTS_SKIP,};/* enough for PES header + length */#define PES_START_SIZE 9#define MAX_PES_HEADER_SIZE (9 + 255)struct PESContext { int pid; int stream_type;// MpegTSContext *ts;// AVFormatContext *stream;// AVStream *st; enum MpegTSState state; /* used to get the format */ int data_index; int total_size; int pes_header_size; int64_t pts, dts; uint8_t header[MAX_PES_HEADER_SIZE];};static int64_t get_pts(const uint8_t *p){ int64_t pts; int val; pts = (int64_t)((p[0] >> 1) & 0x07) << 30; val = (p[1] << 8) | p[2]; pts |= (int64_t)(val >> 1) << 15; val = (p[3] << 8) | p[4]; pts |= (int64_t)(val >> 1); return pts;}#if 0/* return non zero if a packet could be constructed */static void mpegts_push_data(const uint8_t *buf, int buf_size, int is_start){ PESContext *pes = opaque; MpegTSContext *ts = pes->ts; const uint8_t *p; int len, code; if (is_start) { pes->state = MPEGTS_HEADER; pes->data_index = 0; } p = buf; // printf("push data...buf_size = %d \n", buf_size); while (buf_size > 0) { switch(pes->state) { case MPEGTS_HEADER: len = PES_START_SIZE - pes->data_index; if (len > buf_size) len = buf_size; memcpy(pes->header + pes->data_index, p, len); pes->data_index += len; p += len; buf_size -= len; if (pes->data_index == PES_START_SIZE) { /* we got all the PES or section header. We can now decide */#if 1 av_log(ts->stream, AV_LOG_INFO, "PES HEADER:\n"); av_hex_dump(stdout, pes->header, pes->data_index);#endif if (pes->header[0] == 0x00 && pes->header[1] == 0x00 && pes->header[2] == 0x01) { /* it must be an mpeg2 PES stream */ code = pes->header[3] | 0x100; if (!((code >= 0x1c0 && code <= 0x1df) || (code >= 0x1e0 && code <= 0x1ef) || (code == 0x1bd) || (code == 0x1fd))) goto skip; if (!pes->st) { /* allocate stream */ new_pes_av_stream(pes, code); } pes->state = MPEGTS_PESHEADER_FILL; pes->total_size = (pes->header[4] << 8) | pes->header[5]; /* NOTE: a zero total size means the PES size is unbounded */ if (pes->total_size) pes->total_size += 6; pes->pes_header_size = pes->header[8] + 9; // av_hex_dump(stdout, buf, buf_size); } else { /* otherwise, it should be a table */ /* skip packet */ skip: pes->state = MPEGTS_SKIP; continue; } } break; /**********************************************/ /* PES packing parsing */ case MPEGTS_PESHEADER_FILL: len = pes->pes_header_size - pes->data_index; if (len > buf_size) len = buf_size; memcpy(pes->header + pes->data_index, p, len); pes->data_index += len; p += len; buf_size -= len; if (pes->data_index == pes->pes_header_size) { const uint8_t *r; unsigned int flags; flags = pes->header[7]; r = pes->header + 9; pes->pts = AV_NOPTS_VALUE; pes->dts = AV_NOPTS_VALUE; if ((flags & 0xc0) == 0x80) { pes->pts = get_pts(r); r += 5; } else if ((flags & 0xc0) == 0xc0) { pes->pts = get_pts(r); r += 5; pes->dts = get_pts(r); r += 5; } /* we got the full header. We parse it and get the payload */ pes->state = MPEGTS_PAYLOAD; } break; case MPEGTS_PAYLOAD: if (pes->total_size) { len = pes->total_size - pes->data_index; if (len > buf_size) len = buf_size; } else { len = buf_size; } if (len > 0) { AVPacket *pkt = ts->pkt; if (pes->st && av_new_packet(pkt, len) == 0) { memcpy(pkt->data, p, len); pkt->stream_index = pes->st->index; pkt->pts = pes->pts; pkt->dts = pes->dts; /* reset pts values */ pes->pts = AV_NOPTS_VALUE; pes->dts = AV_NOPTS_VALUE; ts->stop_parse = 1; return; } } buf_size = 0; break; case MPEGTS_SKIP: buf_size = 0; break; } }}#endif/* handle one TS packet *///记录每个流的最后的连续计数哿static int last_cc=0;static void handle_packet(const uint8_t *packet, int packet_size){ static int last_cc; int len, pid, cc, cc_ok, afc, is_start; const uint8_t *p, *p_end; pid = ((packet[1] & 0x1f) << 8) | packet[2]; is_start = packet[1] & 0x40; /* continuity check (currently not used) */ cc = (packet[3] & 0xf); cc_ok = (last_cc < 0) || ((((last_cc + 1) & 0x0f) == cc)); last_cc = cc; /* skip adaptation field */ afc = (packet[3] >> 4) & 3; p = packet + 4; if (afc == 0) /* reserved value */ return; if (afc == 2) /* adaptation field only */ return; if (afc == 3) { /* skip adapation field */ p += p[0] + 1; } /* if past the end of packet, ignore */ p_end = packet + packet_size; if (p >= p_end) return; //处理pes数据 // mpegts_push_data(p, p_end - p, is_start);}int main(){ RingBuffer_s rb; u8 buff[TS_PACKET_SIZE]; uint8_t * data; int i; dvbpsi_handle h_dvbpsi; avio_init(&rb, RINGBUFFER_SIZE); wfp = fopen("./1.ts", "wb"); h_dvbpsi = dvbpsi_AttachPAT(DumpPAT, NULL); while(1) { if(read_packet(&rb, buff, TS_PACKET_SIZE) == 0) { //fprintf(wfp, "\n"); uint16_t i_pid = ((uint16_t)(buff[1] & 0x1f) << 8) + buff[2];#if 0 // //if(i_pid == 0x0 && scan_pat == 0) if(i_pid == 0x0 ) { //hex_dump(buff, TS_PACKET_SIZE); //printf("pid = %d\n", i_pid); dvbpsi_PushPacket(h_dvbpsi, buff); //getchar(); //break; } for(i=0;i < pmt_count;i++) { if(i_pid == pmt_array[i].pmt_pid) { printf("pid = %d \n", i_pid); dvbpsi_PushPacket(pmt_array[i].handle, buff); } }#endif if(i_pid == 310)// || i_pid == 320) {#if 0 data = buff + 4; if (buff[3] & 0x20) { /* buf contains an adaptation field */ data = buff + 5 + buff[4]; if (data > buff+TS_PACKET_SIZE) continue; } if (buff[3] & 0x10) //fwrite(data, buff+TS_PACKET_SIZE -data, 1, wfp); //demux (data, buff+TS_PACKET_SIZE, // (buff[1] & 0x40) ? DEMUX_PAYLOAD_START : 0);#endif //demux(buff, buff+TS_PACKET_SIZE, 0); fwrite(buff, TS_PACKET_SIZE, 1, wfp); } //fwrite(buff, TS_PACKET_SIZE, 1, wfp); } else break;// printf("r = %-8d w = %-8d free=%d avail=%d\r", rb.ptr_r, rb.ptr_w, rb_free(&rb), rb_avail(&rb)); //getchar(); } fflush(wfp); fclose(wfp); printf("\ngame over...\n"); system("PAUSE"); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -