int main() { h264_stream_t* h = h264_new(); int bufsiz = fread(filebuf, 1, sizeof(filebuf), stdin); uint8_t* e; uint8_t* p = filebuf; uint8_t* end = filebuf + bufsiz; for (int pp[2]; find_nal_unit(p, end-p, pp, pp+1) > 0; p = e) { e = p + pp[1]; p += pp[0]; if (FILE* fp = fopen("sps.0","w")) { fwrite(p, 1, e-p, fp); fclose(fp); } read_nal_unit(h, p, e-p); debug_nal(h, h->nal); printf("\n"); //h->sps->profile_idc = 0x42; //h->sps->level_idc = 0x33; //h->sps->log2_max_frame_num_minus4 = 0x05; //h->sps->log2_max_pic_order_cnt_lsb_minus4 = 0x06; //h->sps->num_ref_frames = 0x01; //h->sps->profile_idc = 66; //h->sps->level_idc = 10; h->sps->num_ref_frames = 0; //h->sps->log2_max_frame_num_minus4 = 0x05; //h->sps->log2_max_pic_order_cnt_lsb_minus4 = 0x06; //h->sps->direct_8x8_inference_flag = 0; #if 1 h->sps->vui_parameters_present_flag = 1; h->sps->vui.bitstream_restriction_flag = 1; //h->sps->vui.motion_vectors_over_pic_boundaries_flag = 1; //h->sps->vui.log2_max_mv_length_horizontal = 10; //h->sps->vui.log2_max_mv_length_vertical = 10; h->sps->vui.num_reorder_frames = 1; h->sps->vui.max_dec_frame_buffering = 2; #endif debug_nal(h, h->nal); uint8_t out[1024]; int outlen = write_nal_unit(h, out, sizeof(out)); if (FILE* fp = fopen("sps.1","w")) { fwrite(out+1, outlen-1, 1, fp); fclose(fp); } if (h->nal->nal_unit_type == NAL_UNIT_TYPE_SPS) break; p = e; } }
int read_avcc(avcc_t* avcc, h264_stream_t* h, bs_t* b) { avcc->configurationVersion = bs_read_u8(b); avcc->AVCProfileIndication = bs_read_u8(b); avcc->profile_compatibility = bs_read_u8(b); avcc->AVCLevelIndication = bs_read_u8(b); /* int reserved = */ bs_read_u(b, 6); // '111111'b; avcc->lengthSizeMinusOne = bs_read_u(b, 2); /* int reserved = */ bs_read_u(b, 3); // '111'b; avcc->numOfSequenceParameterSets = bs_read_u(b, 5); avcc->sps_table = (sps_t**)calloc(avcc->numOfSequenceParameterSets, sizeof(sps_t*)); int i; for (i = 0; i < avcc->numOfSequenceParameterSets; i++) { int sequenceParameterSetLength = bs_read_u(b, 16); int len = sequenceParameterSetLength; uint8_t* buf = (uint8_t*)malloc(len); len = bs_read_bytes(b, buf, len); int rc = read_nal_unit(h, buf, len); free(buf); if (h->nal->nal_unit_type != NAL_UNIT_TYPE_SPS) { continue; } // TODO report errors if (rc < 0) { continue; } avcc->sps_table[i] = h->sps; // TODO copy data? } avcc->numOfPictureParameterSets = bs_read_u(b, 8); avcc->pps_table = (pps_t**)calloc(avcc->numOfSequenceParameterSets, sizeof(pps_t*)); for (i = 0; i < avcc->numOfPictureParameterSets; i++) { int pictureParameterSetLength = bs_read_u(b, 16); int len = pictureParameterSetLength; uint8_t* buf = (uint8_t*)malloc(len); len = bs_read_bytes(b, buf, len); int rc = read_nal_unit(h, buf, len); free(buf); if (h->nal->nal_unit_type != NAL_UNIT_TYPE_PPS) { continue; } // TODO report errors if (rc < 0) { continue; } avcc->pps_table[i] = h->pps; // TODO copy data? } if (bs_overrun(b)) { return -1; } return bs_pos(b); }
static void ProcessSpsNalu(unsigned char* data, int length) { const char naluHeader[] = {0x00, 0x00, 0x00, 0x01}; h264_stream_t* stream = h264_new(); // Read the old NALU read_nal_unit(stream, &data[sizeof(naluHeader)], length-sizeof(naluHeader)); // Fixup the SPS to what OS X needs to use hardware acceleration stream->sps->num_ref_frames = 1; stream->sps->vui.max_dec_frame_buffering = 1; // Copy the NALU prefix over from the original SPS memcpy(s_LastSps, naluHeader, sizeof(naluHeader)); // Copy the modified NALU data s_LastSpsLength = sizeof(naluHeader) + write_nal_unit(stream, &s_LastSps[sizeof(naluHeader)], sizeof(s_LastSps)-sizeof(naluHeader)); h264_free(stream); }
//自己写的,解析NAL数据的函数 char* probe_nal_unit(char* filename,int data_offset,int data_lenth){ //清空字符串----------------- memset(outputstr,'\0',100000); //tempstr=(char *)malloc(10000); //outputstr=(char *)malloc(100000); //内存用于存放NAL(包含起始码) uint8_t *nal_temp=(uint8_t *)malloc(data_lenth); //从文件读取 FILE *fp=fopen(filename,"rb"); fseek(fp,data_offset,SEEK_SET); fread(nal_temp,data_lenth,1,fp); // read some H264 data into buf int nal_start,nal_end; h264_stream_t* h = h264_new(); find_nal_unit(nal_temp, data_lenth, &nal_start, &nal_end); read_nal_unit(h, &nal_temp[nal_start], nal_end - nal_start); debug_nal(h,h->nal); free(nal_temp); fclose(fp); h264_free(h); return outputstr; }
int main(int argc, char *argv[]) { FILE* infile; uint8_t* buf = (uint8_t*)malloc( BUFSIZE ); h264_stream_t* h = h264_new(); if (argc < 2) { usage(); return EXIT_FAILURE; } int opt_verbose = 1; int opt_probe = 0; #ifdef HAVE_GETOPT_LONG int c; int long_options_index; extern char* optarg; extern int optind; while ( ( c = getopt_long( argc, argv, "o:p:hv", long_options, &long_options_index) ) != -1 ) { switch ( c ) { case 'o': if (h264_dbgfile == NULL) { h264_dbgfile = fopen( optarg, "wt"); } break; case 'p': opt_probe = 1; opt_verbose = 0; break; case 'v': opt_verbose = atoi( optarg ); break; case 'h': default: usage( ); return 1; } } infile = fopen(argv[optind], "rb"); #else infile = fopen(argv[1], "rb"); #endif if (infile == NULL) { fprintf( stderr, "!! Error: could not open file: %s \n", strerror(errno)); exit(EXIT_FAILURE); } if (h264_dbgfile == NULL) { h264_dbgfile = stdout; } size_t rsz = 0; size_t sz = 0; int64_t off = 0; uint8_t* p = buf; int nal_start, nal_end; while (1) { rsz = fread(buf + sz, 1, BUFSIZE - sz, infile); if (rsz == 0) { if (ferror(infile)) { fprintf( stderr, "!! Error: read failed: %s \n", strerror(errno)); break; } break; // if (feof(infile)) } sz += rsz; while (find_nal_unit(p, sz, &nal_start, &nal_end) > 0) { if ( opt_verbose > 0 ) { fprintf( h264_dbgfile, "!! Found NAL at offset %lld (0x%04llX), size %lld (0x%04llX) \n", (long long int)(off + (p - buf) + nal_start), (long long int)(off + (p - buf) + nal_start), (long long int)(nal_end - nal_start), (long long int)(nal_end - nal_start) ); } p += nal_start; read_nal_unit(h, p, nal_end - nal_start); if ( opt_probe && h->nal->nal_unit_type == NAL_UNIT_TYPE_SPS ) { // print codec parameter, per RFC 6381. int constraint_byte = h->sps->constraint_set0_flag << 7; constraint_byte = h->sps->constraint_set1_flag << 6; constraint_byte = h->sps->constraint_set2_flag << 5; constraint_byte = h->sps->constraint_set3_flag << 4; constraint_byte = h->sps->constraint_set4_flag << 3; constraint_byte = h->sps->constraint_set4_flag << 3; fprintf( h264_dbgfile, "codec: avc1.%02X%02X%02X\n",h->sps->profile_idc, constraint_byte, h->sps->level_idc ); // TODO: add more, move to h264_stream (?) break; // we've seen enough, bailing out. } if ( opt_verbose > 0 ) { fprintf( h264_dbgfile, "XX "); debug_bytes(p-4, nal_end - nal_start + 4 >= 16 ? 16: nal_end - nal_start + 4); debug_nal(h, h->nal); } p += (nal_end - nal_start); sz -= nal_end; } // if no NALs found in buffer, discard it if (p == buf) { fprintf( stderr, "!! Did not find any NALs between offset %lld (0x%04llX), size %lld (0x%04llX), discarding \n", (long long int)off, (long long int)off, (long long int)off + sz, (long long int)off + sz); p = buf + sz; sz = 0; } memmove(buf, p, sz); off += p - buf; p = buf; } h264_free(h); free(buf); fclose(h264_dbgfile); fclose(infile); return 0; }
PLENTRY gs_sps_fix(PLENTRY *head, int flags) { PLENTRY entry = *head; const char naluHeader[] = {0x00, 0x00, 0x00, 0x01}; if (replay_sps == 1) { PLENTRY replay_entry = (PLENTRY) malloc(sizeof(*replay_entry) + 128); if (replay_entry == NULL) return NULL; replay_entry->data = (char *) (entry + 1); memcpy(replay_entry->data, naluHeader, sizeof(naluHeader)); h264_stream->sps->profile_idc = H264_PROFILE_HIGH; replay_entry->length = write_nal_unit(h264_stream, replay_entry->data+4, 124) + 4; replay_entry->next = entry; entry = replay_entry; replay_sps = 2; } else if ((entry->data[4] & 0x1F) == NAL_UNIT_TYPE_SPS) { read_nal_unit(h264_stream, entry->data+4, entry->length-4); // Some decoders rely on H264 level to decide how many buffers are needed // Since we only need one frame buffered, we'll set level as low as we can // for known resolution combinations. Otherwise leave the profile alone (currently 5.0) if (initial_width == 1280 && initial_height == 720) h264_stream->sps->level_idc = 32; // Max 5 buffered frames at 1280x720x60 else if (initial_width = 1920 && initial_height == 1080) h264_stream->sps->level_idc = 42; // Max 4 buffered frames at 1920x1080x60 // Some decoders requires a reference frame count of 1 to decode successfully. h264_stream->sps->num_ref_frames = 1; // GFE 2.5.11 changed the SPS to add additional extensions // Some devices don't like these so we remove them here. h264_stream->sps->vui.video_signal_type_present_flag = 0; h264_stream->sps->vui.chroma_loc_info_present_flag = 0; if ((flags & GS_SPS_BITSTREAM_FIXUP) == GS_SPS_BITSTREAM_FIXUP) { // The SPS that comes in the current H264 bytestream doesn't set the bitstream_restriction_flag // or the max_dec_frame_buffering which increases decoding latency on some devices // log2_max_mv_length_horizontal and log2_max_mv_length_vertical are set to more // conservite values by GFE 25.11. We'll let those values stand. if (!h264_stream->sps->vui.bitstream_restriction_flag) { h264_stream->sps->vui.bitstream_restriction_flag = 1; h264_stream->sps->vui.motion_vectors_over_pic_boundaries_flag = 1; h264_stream->sps->vui.max_bits_per_mb_denom = 1; h264_stream->sps->vui.log2_max_mv_length_horizontal = 16; h264_stream->sps->vui.log2_max_mv_length_vertical = 16; h264_stream->sps->vui.num_reorder_frames = 0; } // Some devices throw errors if max_dec_frame_buffering < num_ref_frames h264_stream->sps->vui.max_dec_frame_buffering = 1; // These values are the default for the fields, but they are more aggressive // than what GFE sends in 2.5.11, but it doesn't seem to cause picture problems. h264_stream->sps->vui.max_bytes_per_pic_denom = 2; h264_stream->sps->vui.max_bits_per_mb_denom = 1; } else // Devices that didn't/couldn't get bitstream restrictions before GFE 2.5.11 will continue to not receive them now h264_stream->sps->vui.bitstream_restriction_flag = 0; if ((flags & GS_SPS_BASELINE_HACK) == GS_SPS_BASELINE_HACK && !replay_sps) h264_stream->sps->profile_idc = H264_PROFILE_BASELINE; PLENTRY sps_entry = (PLENTRY) malloc(sizeof(*sps_entry) + 128); if (sps_entry == NULL) return NULL; PLENTRY next = entry->next; free(entry); sps_entry->data = (char*) (sps_entry + 1); memcpy(sps_entry->data, naluHeader, sizeof(naluHeader)); sps_entry->length = write_nal_unit(h264_stream, sps_entry->data+4, 124) + 4; sps_entry->next = next; entry = sps_entry; } else if ((entry->data[4] & 0x1F) == NAL_UNIT_TYPE_PPS) { if ((flags & GS_SPS_BASELINE_HACK) == GS_SPS_BASELINE_HACK && !replay_sps) replay_sps = 1; } *head = entry; return entry; }
int main(int argc, char *argv[]) { uint8_t* buf = (uint8_t*)malloc(BUFSIZE); h264_stream_t* h = h264_new(); if (argc < 2) { printf("h264_analyze, version 0.1.6\n"); printf("Usage: \n"); printf(" h264_analyze stream.h264\n"); printf("where stream.h264 is a raw H264 stream, as produced by JM or x264\n"); } int fd = open(argv[1], O_RDONLY); if (fd == -1) { perror("could not open file"); exit(0); } int rsz = 0; int sz = 0; int64_t off = 0; uint8_t* p = buf; int nal_start, nal_end; while ((rsz = read(fd, buf + sz, BUFSIZE - sz))) { sz += rsz; while (find_nal_unit(p, sz, &nal_start, &nal_end) > 0) { printf("!! Found NAL at offset %"PRId64" (0x%04"PRIX64"), size %"PRId64" (0x%04"PRIX64") \n", (int64_t)(off + (p - buf) + nal_start), (int64_t)(off + (p - buf) + nal_start), (int64_t)(nal_end - nal_start), (int64_t)(nal_end - nal_start) ); p += nal_start; read_nal_unit(h, p, nal_end - nal_start); debug_nal(h, h->nal); p += (nal_end - nal_start); sz -= nal_end; } // if no NALs found in buffer, discard it if (p == buf) { printf("!! Did not find any NALs between offset %"PRId64" (0x%04"PRIX64"), size %"PRId64" (0x%04"PRIX64"), discarding \n", (int64_t)off, (int64_t)off, (int64_t)off + sz, (int64_t)off + sz); p = buf + sz; sz = 0; } memmove(buf, p, sz); off += p - buf; p = buf; } h264_free(h); free(buf); }