nonocast / me

记录和分享技术的博客
http://nonocast.cn
MIT License
20 stars 0 forks source link

学习 rtmp 开发 (Part 3: FLV Format) #271

Open nonocast opened 2 years ago

nonocast commented 2 years ago

FLV: Flash Video.

FLV Layout:

main ()

int main(int argc, char *argv[]) {
  RTMP_LogSetLevel(RTMP_LOGINFO);

  char *prog = argv[0];
  int c;
  while ((c = getopt(argc, argv, "vV")) != -1) {
    switch (c) {
    case 'v':
      RTMP_LogSetLevel(RTMP_LOGDEBUG);
      break;
    case 'V':
      RTMP_LogSetLevel(RTMP_LOGDEBUG2);
      break;
    default:
      usage(prog);
      break;
    }
  }

  RTMP_Log(RTMP_LOGDEBUG, "input: %s", argv[1]);
  infile = fopen(argv[optind], "r");
  if (!infile) {
    usage(argv[0]);
  }

  flv_read_header();
  flv_tag_t *tag;

  while ((tag = flv_read_tag()) != NULL) {
    push_tag(tag);
    print_tag(tag);
    if (feof(infile)) break;
  }

  printf("flv tag count: %lu\n", get_tag_count());

  // video tags
  int i = 0;
  flv_tag_t *current = flv_tag_list_head;
  if (current != NULL) {
    do {
      if (TAGTYPE_VIDEODATA == current->tag_type) {
        ++i;
        RTMP_Log(RTMP_LOGINFO, "%s, t: %d, data size: %d", flv_tag_types[current->tag_type], current->timestamp, current->data_size);
      }
    } while ((current = (flv_tag_t *) current->next) != NULL && i < 10);
  }

  RTMP_Log(RTMP_LOGDEBUG, "the end.");
  release();

  return 0;
}

说明

AVCC and AnnexB

void generate_h264_file() {
  // open outfile
  FILE *outfile = fopen("out.h264", "wb");
  static const byte startcode[] = {0x00, 0x00, 0x00, 0x01};

  // write pps/sps
  flv_tag_t *current = flv_tag_list_head;
  assert(current);

  do {
    if (TAGTYPE_VIDEODATA == current->tag_type) {
      video_tag_t *video_tag = (video_tag_t *) current->data;
      avc_video_packet_t *packet = (avc_video_packet_t *) video_tag->data;
      if (AVC_SEQUENCE_HEADER == packet->avc_packet_type) {
        avc_decoder_configuration_record_t *record = (avc_decoder_configuration_record_t *) packet->data;

        RTMP_LogHex(RTMP_LOGINFO, record->sps, record->sequenceParameterSetLength);
        fwrite(&startcode, sizeof(startcode), 1, outfile);
        fwrite(record->sps, record->sequenceParameterSetLength, 1, outfile);

        RTMP_LogHex(RTMP_LOGINFO, record->pps, record->pictureParameterSetLength);
        fwrite(&startcode, sizeof(startcode), 1, outfile);
        fwrite(record->pps, record->pictureParameterSetLength, 1, outfile);
      } else if (AVC_NALU == packet->avc_packet_type) {
        avc_nalus_t *nalus = (avc_nalus_t *) packet->data;

        // AVCC to AnnexB
        uint32_t offset = 0;
        uint32_t nalu_len = 0;
        while (offset < (nalus->size - 4)) {
          memcpy(&nalu_len, nalus->data + offset, 4);
          nalu_len = ntohl(nalu_len);
          printf(".");
          fwrite(&startcode, sizeof(startcode), 1, outfile);
          fwrite(nalus->data + offset + 4, nalu_len, 1, outfile);

          offset += nalu_len + 4;
        }
      }
    }
  } while ((current = (flv_tag_t *) current->next) != NULL);
  printf("\n");

  fclose(outfile);
}

最后

参考文档