Exemple #1
0
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;
    }
}
Exemple #2
0
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);
}
Exemple #3
0
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;
}
Exemple #6
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;
}
Exemple #7
0
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);
}