📄 elementarystream.cpp
字号:
/* YUNTAI KYONGAdvanced Internet Serviceterm project*/#include "assert.h"#include <malloc.h>#include "elementaryStream.h"#include "fileStream.h"extern void error(char*);elementaryStream::elementaryStream(fileStream *fs, CSocket *sock, unsigned long initTimeStamp, unsigned short initSequence){ assert(fs != NULL); this->sock = sock; this->fs = fs; fs->get_next_data(); next_start_code(); m_slice_start_code = 0x101; m_time_stamp = initTimeStamp; m_seq_num = initSequence;}/* searching start code */int elementaryStream::next_start_code(void){ int size = 0; while(!fs->BYTEALIGNED()) { if(fs->get_bit()) /* get 0s until byte aligned */ error("Not an MPEG file. Cannot find start code"); } /* Check if we are at the start code. If not there is zero byte stuffing */ /* check starting code or skip zero byte stuffing */ while(!fs->next_bits(24, 0x000001)) { if(fs->get_byte()) error("Not an MPEG file. Cannot find start code"); size++; } return size;}/* check how many bytes until next start code */int elementaryStream::find_next_start_code(void){ for(int bytes = 0; !fs->next_bits(24, 0x000001); bytes++) { if( fs->next_bits(24, 0x000001) == -2 ) { printf("end of file!\n"); return -2; } fs->get_bits(8); } return bytes;}int elementaryStream::get_gop_header(unsigned char *payload, int bytesToGo){/* This procedure reads a Gop picture by picture. */ if( !fs->next_bits(32, GROUP_START_CODE) ) return -2; fs->mark(); fs->get_bits(32); // skip group_start_code gop_i.time_code = fs->get_bits(25); // time_code gop_i.closed_gop = fs->get_bit(); // closed_gop gop_i.broken_link = fs->get_bit(); // broken_link next_start_code(); // check exention header if(fs->next_bits(32, EXTENSION_START_CODE)) { fs->get_bits(32); // skip extension_start_code for(gop_i.gop_ext_data_size = 0; !fs->next_bits(24, 0x000001); gop_i.gop_ext_data_size++) gop_i.gop_ext_data[gop_i.gop_ext_data_size] = fs->get_byte(); gop_i.gop_size = 4 + gop_i.gop_ext_data_size; next_start_code(); } else gop_i.gop_ext_data_size = 0; // check user data if(fs->next_bits(32, USER_DATA_START_CODE)) { fs->get_bits(32); // skip user_data_start_code for(gop_i.gop_user_data_size = 0; !fs->next_bits(24, 0x000001); gop_i.gop_user_data_size++) gop_i.gop_user_data[gop_i.gop_user_data_size] = fs->get_byte(); gop_i.gop_size += 4 + gop_i.gop_user_data_size; next_start_code(); } else gop_i.gop_user_data_size = 0; //find_next_start_code(); next_start_code(); //assert( fs->next_bits(32, PICTURE_START_CODE) ); printf("get next start code()" ); if( fs->getSizeFromMark() <= bytesToGo ) { fs->load( payload ); return fs->getSizeFromMark(); } else { fs->rewind(); return -1; } }void elementaryStream::print_picture_header(){ printf("temporal reference: %d\n", picture_h.temporal_reference ); printf("picture config type: %d\n",picture_h.picture_config_type ); printf("vbv_delay: %d\n",picture_h.vbv_delay ); }int elementaryStream::get_picture_header(unsigned char *payload, int bytesToGo){ if(!fs->next_bits(32, PICTURE_START_CODE)) { printf("get_bits: %d\n",fs->get_bits(32)); return -2; } fs->mark(); fs->get_bits(32); // skip picture strat code picture_h.temporal_reference = fs->get_bits(10); // temporal reference picture_h.picture_config_type = fs->get_bits(3); // type of picture picture_h.vbv_delay = fs->get_bits(16); // m_pic_type = picture_h.picture_config_type; if( picture_h.picture_config_type == 2 || picture_h.picture_config_type == 3 ) { picture_h.full_pel_forward_vector = fs->get_bit(); picture_h.forward_f_code = fs->get_bits(3); } if( picture_h.picture_config_type == 3 ) { picture_h.full_pel_backward_vector = fs->get_bit(); picture_h.backward_f_code = fs->get_bits(3); } while( fs->get_bit() ) { fs->get_bits(8); printf("get extra bits!\n"); } next_start_code(); if( fs->getSizeFromMark() <= bytesToGo ) { fs->load( payload ); return fs->getSizeFromMark(); } else { fs->rewind(); return -1; } }int elementaryStream::get_user_data(unsigned char *payload, int bytesToGo){ if(!fs->next_bits(32, USER_DATA_START_CODE)) return -2; fs->mark(); find_next_start_code(); if( fs->getSizeFromMark() <= bytesToGo ) { fs->load( payload ); return fs->getSizeFromMark(); } else { fs->rewind(); return -1; } }int elementaryStream::get_sequence_header(unsigned char *payload, int bytesToGo){ if(!fs->next_bits(32, SEQUENCE_HEADER_CODE)) return -2; fs->mark(); fs->get_bits(32); // skip sequence_header_code sequence_h.horizontal_size_value = fs->get_bits(12); // horizontal_size_value sequence_h.vertical_size_value = fs->get_bits(12); // vertical_size_value sequence_h.aspect_ratio_infomation = fs->get_bits(4); // aspect_ratio_infomation sequence_h.frame_rate_value = fs->get_bits(4); // grame_rate_value sequence_h.bit_rate_value = fs->get_bits(18); // bit_rate_value sequence_h.marker_bit = fs->get_bit(); // marker_bit( should be '1' ) if(!sequence_h.marker_bit) error("Marker bit in SEQUENCE HEADER not set. MPEG file is corrupted"); sequence_h.vbv_buffer_size_value = fs->get_bits(10); // vbv_buffer_size_value sequence_h.constrained_parameters_flag = fs->get_bit(); // constrained_parameters_flag(=0) // check intra_quantiser_matrix and load sequence_h.load_intra_quantiser_matrix = fs->get_bit(); // load_intra_quantiser_matrix if(sequence_h.load_intra_quantiser_matrix) for(int i = 0; i < 64; i++) sequence_h.intra_quantiser_matrix[i] = fs->get_bits(8); // check non_intra_quantiser_matrix and load sequence_h.load_non_intra_quantiser_matrix = fs->get_bit(); if(sequence_h.load_non_intra_quantiser_matrix) for(int i = 0; i < 64; i++) sequence_h.non_intra_quantiser_matrix[i] = fs->get_bits(8); // seek to next start code next_start_code(); // check extention_start_code // TODO: should be parsed to get profile_and_level_indication if(fs->next_bits(32, EXTENSION_START_CODE)) { fs->get_bits(32); // skip extension_start_code for(sequence_h.ext_data_size = 0; !fs->next_bits(24, 0x000001); sequence_h.ext_data_size++) sequence_h.ext_data[sequence_h.ext_data_size] = fs->get_byte(); next_start_code(); } else sequence_h.ext_data_size = 0; next_start_code(); if(fs->next_bits(32, USER_DATA_START_CODE)) { fs->get_bits(32); for(sequence_h.user_data_size = 0; !fs->next_bits(24, 0x000001); sequence_h.user_data_size++) sequence_h.user_data[sequence_h.user_data_size] = fs->get_byte(); next_start_code(); } else sequence_h.user_data_size = 0; sequence_h.sequence_header_size = 12 + (64 * sequence_h.load_intra_quantiser_matrix) + (64 * sequence_h.load_non_intra_quantiser_matrix); if(sequence_h.ext_data_size) sequence_h.sequence_header_size += 4 + sequence_h.ext_data_size; if(sequence_h.user_data) sequence_h.sequence_header_size += 4 + sequence_h.user_data_size; find_next_start_code(); int loadSize = fs->getSizeFromMark(); printf("loadSize: %d\n", loadSize); if( loadSize <= bytesToGo ) { printf("load: %d\n", fs->load( payload ) ); return loadSize; } else { fs->rewind(); return -1; } return 1;}int elementaryStream::get_extension(unsigned char *payload, int bytesToGo){ if(!fs->next_bits(32, EXTENSION_START_CODE)) return -2; fs->mark(); fs->get_bits(32); // skip EXTENSION_START_CODE extension_h.extension_ID = fs->get_bits(4); // 4 extension_h.f_code00 = fs->get_bits(4); // 4 extension_h.f_code01 = fs->get_bits(4); // 4 extension_h.f_code10 = fs->get_bits(4); // 4 extension_h.f_code11 = fs->get_bits(4); // 4 extension_h.intra_dc_precision = fs->get_bits(2); // 2 extension_h.picture_structure = fs->get_bits(2); // 2 extension_h.top_field_first = fs->get_bit(); // 1 extension_h.frame_pred_and_frame_dct = fs->get_bit(); // 1 extension_h.cpmcealment_motion_vectors = fs->get_bit(); // 1 extension_h.q_scale_type = fs->get_bit(); // 1 extension_h.intra_vic_format = fs->get_bit(); // 1 extension_h.alternate_scan = fs->get_bit(); // 1 extension_h.repeat_first_field = fs->get_bit(); // 1 extension_h.chroma_420_type = fs->get_bit(); // 1 extension_h.progressive_frame = fs->get_bit(); // 1 extension_h.composite_display_flag = fs->get_bit(); // 1 if( extension_h.composite_display_flag ) { extension_h.v_axis = fs->get_bit(); // 1 extension_h.field_sequence = fs->get_bits(3); // 3 extension_h.sub_carrier = fs->get_bit(); // 1 extension_h.burst_amplitude = fs->get_bits(7); // 7 extension_h.sub_carrier_phase = fs->get_bits(8); // 8 } next_start_code(); if( fs->getSizeFromMark() <= bytesToGo ) { fs->load( payload ); return fs->getSizeFromMark(); } else { fs->rewind(); return -1; } }void elementaryStream::print_gop(){ printf("Time code %x\n", gop_i.time_code); printf("closed_gop %s\n", gop_i.closed_gop ? "true" : "false"); printf("broken_link %s\n", gop_i.broken_link ? "true" : "false"); if(gop_i.gop_ext_data_size) printf("Extension data exists\n"); if(gop_i.gop_user_data_size) printf("User data exists\n"); printf("Size of gop %d\n", gop_i.gop_size);}int elementaryStream::get_slices(unsigned char *payload, int bytesToGo){ fs->mark(); fs->get_bits(32); // skip slice header if( find_next_start_code() == -2 ) { while( fs->get_byte() != -2 ); fs->load(payload); printf("end of file!\n"); return -2; } while( !(fs->next_bits(32, GROUP_START_CODE) || fs->next_bits(32, SEQUENCE_HEADER_CODE) || fs->next_bits(32, SEQUENCE_END_CODE)|| fs->next_bits(32, PICTURE_START_CODE)) ) { fs->get_bits(32); if( find_next_start_code() == -2 ) { while( fs->get_byte() != -2 ); fs->load(payload); printf("end of file!\n"); return -2; } } return fs->load(payload); //printf("before find_next_start_code()\n" ); //printf("next start code: %u\n", next_start ); //printf("after find_next_start_code()\n" ); //next_start_code(); /* if( fs->getSizeFromMark() <= bytesToGo ) { } else { printf(" **************** insufficient... *************** \n"); fs->rewind(); return -1; } */ }voidelementaryStream::print_sequence_header(){ printf("Got MPEG sequence header\n"); printf("Sequence header size %d\n", sequence_h.sequence_header_size); printf("Frame width %d\n", sequence_h.horizontal_size_value); printf("Frame height %d\n", sequence_h.vertical_size_value); printf("Pel aspect ratio (height to width) %d\n",(sequence_h.aspect_ratio_infomation > 16) ? 0 : sequence_h.aspect_ratio_infomation); printf("Picture rate %d\n", (sequence_h.frame_rate_value > 8) ? 9 : sequence_h.frame_rate_value); printf("Bit rate "); if(sequence_h.bit_rate_value == 0x3ffff) printf("variable\n"); else printf("%d bits/s (%5.2f Kbytes/s)\n", sequence_h.bit_rate_value * 400, (sequence_h.bit_rate_value * 400.0) / 8192); printf("Vbv buffer size %d\n", sequence_h.vbv_buffer_size_value); if(sequence_h.load_intra_quantiser_matrix) printf("Intra quantizer matrix exists\n"); else printf("Uses default intra quantizer matrix\n"); if(sequence_h.load_non_intra_quantiser_matrix) printf("Non intra quantizer matrix exists\n"); else printf("Uses default non intra quantizer matrix\n"); if(sequence_h.ext_data_size) printf("Extension data exists\n"); if(sequence_h.user_data_size) printf("User data exists\n");}void elementaryStream::getVideoSpecficeHeader( unsigned char* vs_header, int end_of_slice, int beginning_of_slce, int seq_header_present, int new_pic_header, int active_N_bit ){ VIDEO_SPECIFIC_HEADER *vh = (VIDEO_SPECIFIC_HEADER*)vs_header; vh->TR = picture_h.temporal_reference; vh->T = 1; vh->MBZ = 0; vh->FFC = picture_h.forward_f_code; vh->FFV = picture_h.full_pel_forward_vector; vh->BFC = picture_h.backward_f_code; vh->FBV = picture_h.full_pel_backward_vector; vh->P = picture_h.picture_config_type; vh->E = end_of_slice; vh->B = beginning_of_slce; vh->S = seq_header_present; vh->N = new_pic_header; vh->AN = active_N_bit;}void elementaryStream::getMPEG2ExtensionHeader( unsigned char* e_h){ MPEG2_VIDEO_SPECIFIC_HEADER_EXTENSION *h = (MPEG2_VIDEO_SPECIFIC_HEADER_EXTENSION*)e_h; /* byte 0,1 */ h->backward_vertical_f_code = extension_h.f_code11; h->backward_horizontal_f_code = extension_h.f_code10; h->forward_vertical_f_code = extension_h.f_code01; h->forward_horizontal_f_code = extension_h.f_code00; h->E = 0; /* Extensions present */ h->X = 0; /* Unused */ /* byte 2,3 */ h->DC = extension_h.intra_dc_precision; /* Intra_DC_precision */ h->PS = extension_h.picture_structure; /* picture_structure */ h->T = extension_h.top_field_first; /* top_field_first */ h->P = extension_h.frame_pred_and_frame_dct; /* frame_predicted_frame_dct */ h->C = extension_h.cpmcealment_motion_vectors; /* concealment_motion_vectors */ h->Q = extension_h.q_scale_type; /* q_scale type */ h->V = extension_h.intra_vic_format; /* intra_vlc_format */ h->A = extension_h.alternate_scan; /* alternate scan */ h->R = extension_h.repeat_first_field; /* repeat_first_field */ h->H = extension_h.chroma_420_type; /* chroma_420_type */ h->G = extension_h.progressive_frame; /* progressive frame */ h->D = extension_h.composite_display_flag; /* composite_display_flag *//* extension_h.v_axis; // 1 extension_h.field_sequence; // 3 extension_h.sub_carrier; // 1 extension_h.burst_amplitude; // 7 extension_h.sub_carrier_phase; // 8*/ }intelementaryStream::sendRTPpacket(unsigned char* payload,int increment, int marker,int payloadSize){ static unsigned char buffer[16384]; static unsigned char RTP_pkt[sizeof(RTP_HEADER)+sizeof(buffer)]; static RTP_HEADER *rtp_header; m_stream_num = 10; rtp_header = (RTP_HEADER *)RTP_pkt; rtp_header->csrc_len = 0; /* expect 0 */ rtp_header->extension = 0; rtp_header->padding = 0; /* expect 0 */ rtp_header->version = RTP_VERSION; /* expect 2 */ /* byte 1 */ rtp_header->payload = MPV_PAYLOAD; rtp_header->marker = marker; /* bytes 2, 3 */ rtp_header->seq_no = htons(m_seq_num++); /* bytes 4-7 */ if( marker ) Sleep( 33 ); // sleep 33 msec if( increment ) { m_time_stamp += (29700*hold); hold = 0; } rtp_header->timestamp = htonl(m_time_stamp); /* bytes 8-11 */ rtp_header->ssrc = htonl(m_stream_num); /* stream number is used here. */ memcpy( RTP_pkt + sizeof(RTP_HEADER), payload, payloadSize ); return sock->write( (void*)&RTP_pkt, sizeof(RTP_HEADER)+payloadSize );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -