static int nuv_header(AVFormatContext *s, AVFormatParameters *ap) { NUVContext *ctx = (NUVContext *)s->priv_data; ByteIOContext *pb = &s->pb; char id_string[12], version_string[5]; double aspect, fps; int is_mythtv, width, height, v_packs, a_packs; int stream_nr = 0; AVStream *vst = NULL, *ast = NULL; get_buffer(pb, id_string, 12); is_mythtv = !memcmp(id_string, "MythTVVideo", 12); get_buffer(pb, version_string, 5); url_fskip(pb, 3); // padding width = get_le32(pb); height = get_le32(pb); get_le32(pb); // unused, "desiredwidth" get_le32(pb); // unused, "desiredheight" get_byte(pb); // 'P' == progressive, 'I' == interlaced url_fskip(pb, 3); // padding aspect = av_int2dbl(get_le64(pb)); fps = av_int2dbl(get_le64(pb)); // number of packets per stream type, -1 means unknown, e.g. streaming v_packs = get_le32(pb); a_packs = get_le32(pb); get_le32(pb); // text get_le32(pb); // keyframe distance (?) if (v_packs) { ctx->v_id = stream_nr++; vst = av_new_stream(s, ctx->v_id); vst->codec->codec_type = CODEC_TYPE_VIDEO; vst->codec->codec_id = CODEC_ID_NUV; vst->codec->codec_tag = MKTAG('R', 'J', 'P', 'G'); vst->codec->width = width; vst->codec->height = height; vst->codec->bits_per_sample = 10; vst->codec->sample_aspect_ratio = av_d2q(aspect, 10000); vst->r_frame_rate = av_d2q(1.0 / fps, 10000); av_set_pts_info(vst, 32, 1, 1000); } else ctx->v_id = -1; if (a_packs) { ctx->a_id = stream_nr++; ast = av_new_stream(s, ctx->a_id); ast->codec->codec_type = CODEC_TYPE_AUDIO; ast->codec->codec_id = CODEC_ID_PCM_S16LE; ast->codec->channels = 2; ast->codec->sample_rate = 44100; ast->codec->bit_rate = 2 * 2 * 44100 * 8; ast->codec->block_align = 2 * 2; ast->codec->bits_per_sample = 16; av_set_pts_info(ast, 32, 1, 1000); } else ctx->a_id = -1; get_codec_data(pb, vst, ast, is_mythtv); return 0; }
static void ff_amf_tag_contents(void *ctx, const uint8_t *data, const uint8_t *data_end) { unsigned int size; char buf[1024]; if (data >= data_end) return; switch (*data++) { case AMF_DATA_TYPE_NUMBER: av_log(ctx, AV_LOG_DEBUG, " number %g\n", av_int2dbl(AV_RB64(data))); return; case AMF_DATA_TYPE_BOOL: av_log(ctx, AV_LOG_DEBUG, " bool %d\n", *data); return; case AMF_DATA_TYPE_STRING: case AMF_DATA_TYPE_LONG_STRING: if (data[-1] == AMF_DATA_TYPE_STRING) { size = bytestream_get_be16(&data); } else { size = bytestream_get_be32(&data); } size = FFMIN(size, sizeof(buf) - 1); memcpy(buf, data, size); buf[size] = 0; av_log(ctx, AV_LOG_DEBUG, " string '%s'\n", buf); return; case AMF_DATA_TYPE_NULL: av_log(ctx, AV_LOG_DEBUG, " NULL\n"); return; case AMF_DATA_TYPE_ARRAY: data += 4; case AMF_DATA_TYPE_OBJECT: av_log(ctx, AV_LOG_DEBUG, " {\n"); for (;;) { int t; size = bytestream_get_be16(&data); av_strlcpy(buf, data, FFMIN(sizeof(buf), size + 1)); if (!size) { av_log(ctx, AV_LOG_DEBUG, " }\n"); data++; break; } if (size >= data_end - data) return; data += size; av_log(ctx, AV_LOG_DEBUG, " %s: ", buf); ff_amf_tag_contents(ctx, data, data_end); t = ff_amf_tag_size(data, data_end); if (t < 0 || t >= data_end - data) return; data += t; } return; case AMF_DATA_TYPE_OBJECT_END: av_log(ctx, AV_LOG_DEBUG, " }\n"); return; default: return; } }
/* * Read the next element as a float. */ long double ebml_read_float(stream_t *s, uint64_t *length) { long double value; uint64_t len; int l; len = ebml_read_length(s, &l); switch (len) { case 4: value = av_int2flt(stream_read_dword(s)); break; case 8: value = av_int2dbl(stream_read_qword(s)); break; default: return EBML_FLOAT_INVALID; } if (length) *length = len + l; return value; }
static double ebml_parse_float(uint8_t *data, int length) { assert(length == 4 || length == 8); uint64_t i = ebml_parse_uint(data, length); if (length == 4) return av_int2flt(i); else return av_int2dbl(i); }
int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end, const uint8_t *name, uint8_t *dst, int dst_size) { int namelen = strlen((char *)name); int len; while (*data != AMF_DATA_TYPE_OBJECT && data < data_end) { len = ff_amf_tag_size(data, data_end); if (len < 0) len = data_end - data; data += len; } if (data_end - data < 3) return -1; data++; for (;;) { int size = bytestream_get_be16(&data); if (!size) break; if (data + size >= data_end || data + size < data) return -1; data += size; if (size == namelen && !memcmp(data-size, name, namelen)) { switch (*data++) { case AMF_DATA_TYPE_NUMBER: snprintf((char *)dst, dst_size, "%g", av_int2dbl(AV_RB64(data))); break; case AMF_DATA_TYPE_BOOL: snprintf((char *)dst, dst_size, "%s", *data ? "true" : "false"); break; case AMF_DATA_TYPE_STRING: len = bytestream_get_be16(&data); av_strlcpy((char *)dst, (const char*)data, FFMIN(len+1, dst_size)); break; default: return -1; } return 0; } len = ff_amf_tag_size(data, data_end); if (len < 0 || data + len >= data_end || data + len < data) return -1; data += len; } return -1; }
float ADM_ebml::readFloat(uint32_t n) { if(n!=4 && n!=8) ADM_assert(0); switch(n) { case 4: { uint32_t u4=readUnsignedInt(4); return av_int2flt(u4); } case 8: { uint64_t u8=readUnsignedInt(8); return av_int2dbl(u8); } default: ADM_assert(0); } }
/** Read audio description chunk */ static int read_desc_chunk(AVFormatContext *s) { ByteIOContext *pb = s->pb; CaffContext *caf = s->priv_data; AVStream *st; int flags; /* new audio stream */ st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); /* parse format description */ st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->sample_rate = av_int2dbl(get_be64(pb)); st->codec->codec_tag = get_be32(pb); flags = get_be32(pb); caf->bytes_per_packet = get_be32(pb); st->codec->block_align = caf->bytes_per_packet; caf->frames_per_packet = get_be32(pb); st->codec->channels = get_be32(pb); st->codec->bits_per_coded_sample = get_be32(pb); /* calculate bit rate for constant size packets */ if (caf->frames_per_packet > 0 && caf->bytes_per_packet > 0) { st->codec->bit_rate = (uint64_t)st->codec->sample_rate * (uint64_t)caf->bytes_per_packet * 8 / (uint64_t)caf->frames_per_packet; } else { st->codec->bit_rate = 0; } /* determine codec */ if (st->codec->codec_tag == MKBETAG('l','p','c','m')) st->codec->codec_id = ff_mov_get_lpcm_codec_id(st->codec->bits_per_coded_sample, (flags ^ 0x2) | 0x4); else st->codec->codec_id = ff_codec_get_id(ff_codec_caf_tags, st->codec->codec_tag); return 0; }
static int nuv_header(AVFormatContext *s, AVFormatParameters *ap) { NUVContext *ctx = s->priv_data; AVIOContext *pb = s->pb; char id_string[12]; double aspect, fps; int is_mythtv, width, height, v_packs, a_packs; int stream_nr = 0; AVStream *vst = NULL, *ast = NULL; avio_read(pb, id_string, 12); is_mythtv = !memcmp(id_string, "MythTVVideo", 12); avio_skip(pb, 5); // version string avio_skip(pb, 3); // padding width = avio_rl32(pb); height = avio_rl32(pb); avio_rl32(pb); // unused, "desiredwidth" avio_rl32(pb); // unused, "desiredheight" avio_r8(pb); // 'P' == progressive, 'I' == interlaced avio_skip(pb, 3); // padding aspect = av_int2dbl(avio_rl64(pb)); if (aspect > 0.9999 && aspect < 1.0001) aspect = 4.0 / 3.0; fps = av_int2dbl(avio_rl64(pb)); // number of packets per stream type, -1 means unknown, e.g. streaming v_packs = avio_rl32(pb); a_packs = avio_rl32(pb); avio_rl32(pb); // text avio_rl32(pb); // keyframe distance (?) if (v_packs) { ctx->v_id = stream_nr++; vst = avformat_new_stream(s, NULL); if (!vst) return AVERROR(ENOMEM); vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; vst->codec->codec_id = CODEC_ID_NUV; vst->codec->width = width; vst->codec->height = height; vst->codec->bits_per_coded_sample = 10; vst->sample_aspect_ratio = av_d2q(aspect * height / width, 10000); vst->r_frame_rate = av_d2q(fps, 60000); av_set_pts_info(vst, 32, 1, 1000); } else ctx->v_id = -1; if (a_packs) { ctx->a_id = stream_nr++; ast = avformat_new_stream(s, NULL); if (!ast) return AVERROR(ENOMEM); ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; ast->codec->codec_id = CODEC_ID_PCM_S16LE; ast->codec->channels = 2; ast->codec->sample_rate = 44100; ast->codec->bit_rate = 2 * 2 * 44100 * 8; ast->codec->block_align = 2 * 2; ast->codec->bits_per_coded_sample = 16; av_set_pts_info(ast, 32, 1, 1000); } else ctx->a_id = -1; get_codec_data(pb, vst, ast, is_mythtv); ctx->rtjpg_video = vst && vst->codec->codec_id == CODEC_ID_NUV; return 0; }
static int sox_read_header(AVFormatContext *s, AVFormatParameters *ap) { ByteIOContext *pb = s->pb; unsigned header_size, comment_size; double sample_rate, sample_rate_frac; AVStream *st; st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM); st->codec->codec_type = CODEC_TYPE_AUDIO; if (get_le32(pb) == SOX_TAG) { st->codec->codec_id = CODEC_ID_PCM_S32LE; header_size = get_le32(pb); url_fskip(pb, 8); /* sample count */ sample_rate = av_int2dbl(get_le64(pb)); st->codec->channels = get_le32(pb); comment_size = get_le32(pb); } else { st->codec->codec_id = CODEC_ID_PCM_S32BE; header_size = get_be32(pb); url_fskip(pb, 8); /* sample count */ sample_rate = av_int2dbl(get_be64(pb)); st->codec->channels = get_be32(pb); comment_size = get_be32(pb); } if (comment_size > 0xFFFFFFFFU - SOX_FIXED_HDR - 4U) { av_log(s, AV_LOG_ERROR, "invalid comment size (%u)\n", comment_size); return -1; } if (sample_rate <= 0 || sample_rate > INT_MAX) { av_log(s, AV_LOG_ERROR, "invalid sample rate (%f)\n", sample_rate); return -1; } sample_rate_frac = sample_rate - floor(sample_rate); if (sample_rate_frac) av_log(s, AV_LOG_WARNING, "truncating fractional part of sample rate (%f)\n", sample_rate_frac); if ((header_size + 4) & 7 || header_size < SOX_FIXED_HDR + comment_size || st->codec->channels > 65535) /* Reserve top 16 bits */ { av_log(s, AV_LOG_ERROR, "invalid header\n"); return -1; } if (comment_size && comment_size + FF_INPUT_BUFFER_PADDING_SIZE >= comment_size) { char *comment = av_mallocz(comment_size + FF_INPUT_BUFFER_PADDING_SIZE); if (get_buffer(pb, comment, comment_size) != comment_size) { av_freep(&comment); return AVERROR_IO; } av_metadata_set(&s->metadata, "comment", comment); av_freep(&comment); } url_fskip(pb, header_size - SOX_FIXED_HDR - comment_size); st->codec->sample_rate = sample_rate; st->codec->bits_per_coded_sample = 32; st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_coded_sample * st->codec->channels; st->codec->block_align = st->codec->bits_per_coded_sample * st->codec->channels / 8; av_set_pts_info(st, 64, 1, st->codec->sample_rate); return 0; }
static int sox_read_header(AVFormatContext *s, AVFormatParameters *ap) { AVIOContext *pb = s->pb; unsigned header_size, comment_size; double sample_rate, sample_rate_frac; AVStream *st; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; if (avio_rl32(pb) == SOX_TAG) { st->codec->codec_id = CODEC_ID_PCM_S32LE; header_size = avio_rl32(pb); avio_skip(pb, 8); /* sample count */ sample_rate = av_int2dbl(avio_rl64(pb)); st->codec->channels = avio_rl32(pb); comment_size = avio_rl32(pb); } else { st->codec->codec_id = CODEC_ID_PCM_S32BE; header_size = avio_rb32(pb); avio_skip(pb, 8); /* sample count */ sample_rate = av_int2dbl(avio_rb64(pb)); st->codec->channels = avio_rb32(pb); comment_size = avio_rb32(pb); } if (comment_size > 0xFFFFFFFFU - SOX_FIXED_HDR - 4U) { av_log(s, AV_LOG_ERROR, "invalid comment size (%u)\n", comment_size); return -1; } if (sample_rate <= 0 || sample_rate > INT_MAX) { av_log(s, AV_LOG_ERROR, "invalid sample rate (%f)\n", sample_rate); return -1; } sample_rate_frac = sample_rate - floor(sample_rate); if (sample_rate_frac) av_log(s, AV_LOG_WARNING, "truncating fractional part of sample rate (%f)\n", sample_rate_frac); if ((header_size + 4) & 7 || header_size < SOX_FIXED_HDR + comment_size || st->codec->channels > 65535) /* Reserve top 16 bits */ { av_log(s, AV_LOG_ERROR, "invalid header\n"); return -1; } if (comment_size && comment_size < UINT_MAX) { char *comment = av_malloc(comment_size+1); if(!comment) return AVERROR(ENOMEM); if (avio_read(pb, comment, comment_size) != comment_size) { av_freep(&comment); return AVERROR(EIO); } comment[comment_size] = 0; av_dict_set(&s->metadata, "comment", comment, AV_DICT_DONT_STRDUP_VAL); } avio_skip(pb, header_size - SOX_FIXED_HDR - comment_size); st->codec->sample_rate = sample_rate; st->codec->bits_per_coded_sample = 32; st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_coded_sample * st->codec->channels; st->codec->block_align = st->codec->bits_per_coded_sample * st->codec->channels / 8; avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); return 0; }
/** \fn parseOneMeta */ bool flvHeader::parseOneMeta(const char *stri,uint64_t endPos,bool &end) { static int nesting=0; nesting++; int type=read8(); Nest(); printf("\n>> type :%d ",type); aprintf("nesting = %d, at %d, : ,end=%d",nesting,ftello(_fd),endPos); switch(type) { case AMF_DATA_TYPE_OBJECT_END: Nest(); printf("** Object end**.\n"); if(ftello(_fd)>=endPos-4) { fseek(_fd,endPos,SEEK_SET); } end=true; nesting--; break; case AMF_DATA_TYPE_OBJECT: { printf("\n"); bool myEnd=false; while(ftello(_fd)<endPos-4 && myEnd==false) { Nest();aprintf("Pos = %d, end=%d (object)\n",ftello(_fd),endPos-4); char *o=readFlvString(); Nest(); printf("\t ** Object**:%s",o); if(false==parseOneMeta(o,endPos,myEnd)) return false; /* char objType=read8(); printf("-->%d",objType); if(objType!=10) { ADM_warning("type is not strict array\n"); goto xxer; } int count=read32(); printf(", count=%d\n",count); for(int i=0;i<count;i++) { if(false==parseOneMeta(endPos)) return false; } break; */ } break; } case AMF_DATA_TYPE_ARRAY: { uint32_t len=read32(); Nest();printf("\n**[FLV] Array : %"PRIu32" entries**\n",len); bool theend; for(int i=0;i<len && ftello(_fd)<endPos-4;i++) if(false==parseOneMeta("",endPos,theend)) return false; Nest();printf("\n"); break; } case AMF_DATA_TYPE_DATE: Skip(8+2);break; case AMF_DATA_TYPE_NUMBER: { float val; uint64_t hi,lo; hi=read32();lo=read32(); hi=(hi<<32)+lo; val=(float)av_int2dbl(hi); printf("->%f",val); setProperties(stri,val); } ;break; case AMF_DATA_TYPE_STRING: { int r=read16(); #if 1 Nest();printf("<"); for(int i=0;i<r;i++) { printf("%c",read8()); } printf(">"); #else Skip(r);} #endif } break; case AMF_DATA_TYPE_BOOL: read8();break; case AMF_DATA_TYPE_MIXEDARRAY: { read32(); while(ftello(_fd)<endPos-4) { char *o=readFlvString(); bool theend; if(!o) break; Nest();printf("** MixedArray:%s **",o); if(false==parseOneMeta(o,endPos,theend)) return false; } if(read8()!=AMF_END_OF_OBJECT) return false; } break; default : printf("Unknown type=%d\n",type);ADM_assert(0); }
/** \fn parseMetaData \brief */ uint8_t flvHeader::parseMetaData(uint32_t remaining) { uint32_t endPos=ftello(_fd)+remaining; { // Check the first one is onMetaData... uint8_t type=read8(); if(type!=AMF_DATA_TYPE_STRING) // String! goto endit; char *z=readFlvString(); printf("[FlashString] %s\n",z); if(z && strncmp(z,"onMetaData",10)) goto endit; // Normally the next one is mixed array Skip(4); Skip(1); while(ftello(_fd)<endPos-4) { char *s=readFlvString(); printf("[FlvType] :%d String : %s",type,s); type=read8(); switch(type) { case AMF_DATA_TYPE_DATE: Skip(8+2); break; case AMF_DATA_TYPE_NUMBER: { float val; uint64_t hi,lo; hi=read32(); lo=read32(); hi=(hi<<32)+lo; val=(float)av_int2dbl(hi); printf("->%f\n",val); setProperties(s,val); } ; break; case AMF_DATA_TYPE_STRING: { int r=read16(); Skip(r); } break; case AMF_DATA_TYPE_BOOL: read8(); break; case AMF_DATA_TYPE_OBJECT: goto endit; // unsupported for the moment default : printf("\n"); ADM_assert(0); } printf("\n"); } // Process them... } endit: fseeko(_fd,endPos,SEEK_SET); return 1; }