/** * Routine to correct a possibly erroneous framerate being fed to us. * Xvid currently chokes on framerates where the ticks per frame is * extremely large. This function works to correct problems in this area * by estimating a new framerate and taking the simpler fraction of * the two presented. * * @param avctx Context that contains the framerate to correct. */ static void xvid_correct_framerate(AVCodecContext *avctx) { int frate, fbase; int est_frate, est_fbase; int gcd; float est_fps, fps; frate = avctx->time_base.den; fbase = avctx->time_base.num; gcd = av_gcd(frate, fbase); if( gcd > 1 ) { frate /= gcd; fbase /= gcd; } if( frate <= 65000 && fbase <= 65000 ) { avctx->time_base.den = frate; avctx->time_base.num = fbase; return; } fps = (float)frate / (float)fbase; est_fps = roundf(fps * 1000.0) / 1000.0; est_frate = (int)est_fps; if( est_fps > (int)est_fps ) { est_frate = (est_frate + 1) * 1000; est_fbase = (int)roundf((float)est_frate / est_fps); } else est_fbase = 1; gcd = av_gcd(est_frate, est_fbase); if( gcd > 1 ) { est_frate /= gcd; est_fbase /= gcd; } if( fbase > est_fbase ) { avctx->time_base.den = est_frate; avctx->time_base.num = est_fbase; av_log(avctx, AV_LOG_DEBUG, "Xvid: framerate re-estimated: %.2f, %.3f%% correction\n", est_fps, (((est_fps - fps)/fps) * 100.0)); } else { avctx->time_base.den = frate; avctx->time_base.num = fbase; } }
static int find_frame_rate_index(MpegEncContext *s){ int i; AVRational bestq= (AVRational){0, 0}; AVRational ext; AVRational target = av_inv_q(s->avctx->time_base); for(i=1;i<14;i++) { if(s->avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL && i>=9) break; for (ext.num=1; ext.num <= 4; ext.num++) { for (ext.den=1; ext.den <= 32; ext.den++) { AVRational q = av_mul_q(ext, ff_mpeg12_frame_rate_tab[i]); if(s->codec_id != AV_CODEC_ID_MPEG2VIDEO && (ext.den!=1 || ext.num!=1)) continue; if(av_gcd(ext.den, ext.num) != 1) continue; if( bestq.num==0 || av_nearer_q(target, bestq, q) < 0 || ext.num==1 && ext.den==1 && av_nearer_q(target, bestq, q) == 0){ bestq = q; s->frame_rate_index= i; s->mpeg2_frame_rate_ext.num = ext.num; s->mpeg2_frame_rate_ext.den = ext.den; } } } } if(av_cmp_q(target, bestq)) return -1; else return 0; }
static av_cold int init(AVFilterContext *ctx, const char *args) { AspectContext *aspect = ctx->priv; double ratio; int64_t gcd; char c = 0; if (args) { if (sscanf(args, "%d:%d%c", &aspect->aspect.num, &aspect->aspect.den, &c) != 2) if (sscanf(args, "%lf%c", &ratio, &c) == 1) aspect->aspect = av_d2q(ratio, 100); if (c || aspect->aspect.num <= 0 || aspect->aspect.den <= 0) { av_log(ctx, AV_LOG_ERROR, "Invalid string '%s' for aspect ratio.\n", args); return AVERROR(EINVAL); } gcd = av_gcd(FFABS(aspect->aspect.num), FFABS(aspect->aspect.den)); if (gcd) { aspect->aspect.num /= gcd; aspect->aspect.den /= gcd; } } if (aspect->aspect.den == 0) aspect->aspect = (AVRational) {0, 1}; av_log(ctx, AV_LOG_VERBOSE, "a:%d/%d\n", aspect->aspect.num, aspect->aspect.den); return 0; }
int av_parse_ratio(AVRational *q, const char *str, int max, int log_offset, void *log_ctx) { char c; int ret; int64_t gcd; if (sscanf(str, "%d:%d%c", &q->num, &q->den, &c) != 2) { double d; ret = av_expr_parse_and_eval(&d, str, NULL, NULL, NULL, NULL, NULL, NULL, NULL, log_offset, log_ctx); if (ret < 0) return ret; *q = av_d2q(d, max); } gcd = av_gcd(FFABS(q->num), FFABS(q->den)); if (gcd) { q->num /= gcd; q->den /= gcd; } return 0; }
/* send an integer number of samples and compute time stamp and fill the rtp send buffer before sending. */ static int rtp_send_samples(AVFormatContext *s1, const uint8_t *buf1, int size, int sample_size_bits) { RTPMuxContext *s = s1->priv_data; int len, max_packet_size, n; /* Calculate the number of bytes to get samples aligned on a byte border */ int aligned_samples_size = sample_size_bits/av_gcd(sample_size_bits, 8); max_packet_size = (s->max_payload_size / aligned_samples_size) * aligned_samples_size; /* Not needed, but who knows. Don't check if samples aren't an even number of bytes. */ if ((sample_size_bits % 8) == 0 && ((8 * size) % sample_size_bits) != 0) return AVERROR(EINVAL); n = 0; while (size > 0) { s->buf_ptr = s->buf; len = FFMIN(max_packet_size, size); /* copy data */ memcpy(s->buf_ptr, buf1, len); s->buf_ptr += len; buf1 += len; size -= len; s->timestamp = s->cur_timestamp + n * 8 / sample_size_bits; ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 0); n += (s->buf_ptr - s->buf); } return 0; }
void ff_parse_specific_params(AVStream *st, int *au_rate, int *au_ssize, int *au_scale) { AVCodecContext *codec = st->codec; int gcd; int audio_frame_size; audio_frame_size = av_get_audio_frame_duration(codec, 0); *au_ssize = codec->block_align; if (audio_frame_size && codec->sample_rate) { *au_scale = audio_frame_size; *au_rate = codec->sample_rate; } else if (codec->codec_type == AVMEDIA_TYPE_VIDEO || codec->codec_type == AVMEDIA_TYPE_DATA || codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { *au_scale = st->time_base.num; *au_rate = st->time_base.den; } else { *au_scale = codec->block_align ? codec->block_align * 8 : 8; *au_rate = codec->bit_rate ? codec->bit_rate : 8 * codec->sample_rate; } gcd = av_gcd(*au_scale, *au_rate); *au_scale /= gcd; *au_rate /= gcd; }
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) { AspectContext *aspect = ctx->priv; double ratio; int64_t gcd; if(args) { if(sscanf(args, "%d:%d", &aspect->aspect.num, &aspect->aspect.den) < 2) { if(sscanf(args, "%lf", &ratio) < 1) return -1; aspect->aspect = av_d2q(ratio, 100); } else { gcd = av_gcd(FFABS(aspect->aspect.num), FFABS(aspect->aspect.den)); if(gcd) { aspect->aspect.num /= gcd; aspect->aspect.den /= gcd; } } } if(aspect->aspect.den == 0) aspect->aspect = (AVRational) {0, 1}; return 0; }
void ff_parse_specific_params(AVStream *st, int *au_rate, int *au_ssize, int *au_scale) { AVCodecContext *codec = st->codec; int gcd; int audio_frame_size; /* We use the known constant frame size for the codec if known, otherwise * fall back on using AVCodecContext.frame_size, which is not as reliable * for indicating packet duration. */ audio_frame_size = av_get_audio_frame_duration(codec, 0); if (!audio_frame_size) audio_frame_size = codec->frame_size; *au_ssize = codec->block_align; if (audio_frame_size && codec->sample_rate) { *au_scale = audio_frame_size; *au_rate = codec->sample_rate; } else if (codec->codec_type == AVMEDIA_TYPE_VIDEO || codec->codec_type == AVMEDIA_TYPE_DATA || codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { *au_scale = st->time_base.num; *au_rate = st->time_base.den; } else { *au_scale = codec->block_align ? codec->block_align * 8 : 8; *au_rate = codec->bit_rate ? codec->bit_rate : 8 * codec->sample_rate; } gcd = av_gcd(*au_scale, *au_rate); *au_scale /= gcd; *au_rate /= gcd; }
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max) { AVRational a0 = { 0, 1 }, a1 = { 1, 0 }; int sign = (num < 0) ^ (den < 0); int64_t gcd = av_gcd(FFABS(num), FFABS(den)); if (gcd) { num = FFABS(num) / gcd; den = FFABS(den) / gcd; } if (num <= max && den <= max) { a1 = (AVRational) { num, den }; den = 0; } while (den) { uint64_t x = num / den; int64_t next_den = num - den * x; int64_t a2n = x * a1.num + a0.num; int64_t a2d = x * a1.den + a0.den; if (a2n > max || a2d > max) { if (a1.num) x = (max - a0.num) / a1.num; if (a1.den) x = FFMIN(x, (max - a0.den) / a1.den); if (den * (2 * x * a1.den + a0.den) > num * a1.den) a1 = (AVRational) { x * a1.num + a0.num, x * a1.den + a0.den }; break; } a0 = a1; a1 = (AVRational) { a2n, a2d }; num = den; den = next_den; } av_assert2(av_gcd(a1.num, a1.den) <= 1U); av_assert2(a1.num <= max && a1.den <= max); *dst_num = sign ? -a1.num : a1.num; *dst_den = a1.den; return den == 0; }
void ff_parse_specific_params(AVCodecContext *stream, int *au_rate, int *au_ssize, int *au_scale) { int gcd; *au_ssize= stream->block_align; if(stream->frame_size && stream->sample_rate){ *au_scale=stream->frame_size; *au_rate= stream->sample_rate; }else if(stream->codec_type == AVMEDIA_TYPE_VIDEO || stream->codec_type == AVMEDIA_TYPE_DATA || stream->codec_type == AVMEDIA_TYPE_SUBTITLE){ *au_scale= stream->time_base.num; *au_rate = stream->time_base.den; }else{ *au_scale= stream->block_align ? stream->block_align*8 : 8; *au_rate = stream->bit_rate ? stream->bit_rate : 8*stream->sample_rate; } gcd= av_gcd(*au_scale, *au_rate); *au_scale /= gcd; *au_rate /= gcd; }
static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; int exact; // common timebase computation: AVRational tb1 = ctx->inputs[MAIN ]->time_base; AVRational tb2 = ctx->inputs[OVERLAY]->time_base; AVRational *tb = &ctx->outputs[0]->time_base; exact = av_reduce(&tb->num, &tb->den, av_gcd((int64_t)tb1.num * tb2.den, (int64_t)tb2.num * tb1.den), (int64_t)tb1.den * tb2.den, INT_MAX); av_log(ctx, AV_LOG_INFO, "main_tb:%d/%d overlay_tb:%d/%d -> tb:%d/%d exact:%d\n", tb1.num, tb1.den, tb2.num, tb2.den, tb->num, tb->den, exact); if (!exact) av_log(ctx, AV_LOG_WARNING, "Timestamp conversion inexact, timestamp information loss may occurr\n"); outlink->w = ctx->inputs[MAIN]->w; outlink->h = ctx->inputs[MAIN]->h; return 0; }
static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i) { lavf_priv_t *priv= demuxer->priv; AVStream *st= avfc->streams[i]; AVCodecContext *codec= st->codec; char *stream_type = NULL; int stream_id; AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0); AVDictionaryEntry *title= av_dict_get(st->metadata, "title", NULL, 0); int g; switch(codec->codec_type){ case AVMEDIA_TYPE_AUDIO:{ WAVEFORMATEX *wf; sh_audio_t* sh_audio; sh_audio = new_sh_audio_aid(demuxer, i, priv->audio_streams, lang ? lang->value : NULL); if(!sh_audio) break; stream_type = "audio"; priv->astreams[priv->audio_streams] = i; wf= calloc(sizeof(*wf) + codec->extradata_size, 1); codec->codec_tag = mp_codec_id2tag(codec->codec_id, codec->codec_tag, 1); wf->wFormatTag= codec->codec_tag; wf->nChannels= codec->channels; wf->nSamplesPerSec= codec->sample_rate; wf->nAvgBytesPerSec= codec->bit_rate/8; wf->nBlockAlign= codec->block_align ? codec->block_align : 1; wf->wBitsPerSample= codec->bits_per_coded_sample; wf->cbSize= codec->extradata_size; if(codec->extradata_size) memcpy(wf + 1, codec->extradata, codec->extradata_size); sh_audio->wf= wf; sh_audio->audio.dwSampleSize= codec->block_align; if(codec->frame_size && codec->sample_rate){ sh_audio->audio.dwScale=codec->frame_size; sh_audio->audio.dwRate= codec->sample_rate; }else{ sh_audio->audio.dwScale= codec->block_align ? codec->block_align*8 : 8; sh_audio->audio.dwRate = codec->bit_rate; } g= av_gcd(sh_audio->audio.dwScale, sh_audio->audio.dwRate); sh_audio->audio.dwScale /= g; sh_audio->audio.dwRate /= g; // printf("sca:%d rat:%d fs:%d sr:%d ba:%d\n", sh_audio->audio.dwScale, sh_audio->audio.dwRate, codec->frame_size, codec->sample_rate, codec->block_align); sh_audio->ds= demuxer->audio; sh_audio->format= codec->codec_tag; sh_audio->channels= codec->channels; sh_audio->samplerate= codec->sample_rate; sh_audio->i_bps= codec->bit_rate/8; switch (codec->codec_id) { case CODEC_ID_PCM_S8: case CODEC_ID_PCM_U8: sh_audio->samplesize = 1; break; case CODEC_ID_PCM_S16LE: case CODEC_ID_PCM_S16BE: case CODEC_ID_PCM_U16LE: case CODEC_ID_PCM_U16BE: sh_audio->samplesize = 2; break; case CODEC_ID_PCM_ALAW: sh_audio->format = 0x6; break; case CODEC_ID_PCM_MULAW: sh_audio->format = 0x7; break; } if (title && title->value) mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_NAME=%s\n", priv->audio_streams, title->value); if (st->disposition & AV_DISPOSITION_DEFAULT) sh_audio->default_track = 1; if(mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_audio->wf, MSGL_V); // select the first audio stream if auto-selection is requested if (demuxer->audio->id == -1) { demuxer->audio->id = i; demuxer->audio->sh= demuxer->a_streams[i]; } if (demuxer->audio->id != i) st->discard= AVDISCARD_ALL; stream_id = priv->audio_streams++; break; } case AVMEDIA_TYPE_VIDEO:{ sh_video_t* sh_video; BITMAPINFOHEADER *bih; sh_video=new_sh_video_vid(demuxer, i, priv->video_streams); if(!sh_video) break; stream_type = "video"; priv->vstreams[priv->video_streams] = i; bih=calloc(sizeof(*bih) + codec->extradata_size,1); if(codec->codec_id == CODEC_ID_RAWVIDEO) { switch (codec->pix_fmt) { case PIX_FMT_RGB24: codec->codec_tag= MKTAG(24, 'B', 'G', 'R'); case PIX_FMT_BGR24: codec->codec_tag= MKTAG(24, 'R', 'G', 'B'); } } codec->codec_tag = mp_codec_id2tag(codec->codec_id, codec->codec_tag, 0); bih->biSize= sizeof(*bih) + codec->extradata_size; bih->biWidth= codec->width; bih->biHeight= codec->height; bih->biBitCount= codec->bits_per_coded_sample; bih->biSizeImage = bih->biWidth * bih->biHeight * bih->biBitCount/8; bih->biCompression= codec->codec_tag; sh_video->bih= bih; sh_video->disp_w= codec->width; sh_video->disp_h= codec->height; if (st->time_base.den) { /* if container has time_base, use that */ sh_video->video.dwRate= st->time_base.den; sh_video->video.dwScale= st->time_base.num; } else { sh_video->video.dwRate= codec->time_base.den; sh_video->video.dwScale= codec->time_base.num; } sh_video->fps=av_q2d(st->r_frame_rate); sh_video->frametime=1/av_q2d(st->r_frame_rate); sh_video->format=bih->biCompression; if(st->sample_aspect_ratio.num) sh_video->aspect = codec->width * st->sample_aspect_ratio.num / (float)(codec->height * st->sample_aspect_ratio.den); else sh_video->aspect=codec->width * codec->sample_aspect_ratio.num / (float)(codec->height * codec->sample_aspect_ratio.den); sh_video->i_bps=codec->bit_rate/8; if (title && title->value) mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VID_%d_NAME=%s\n", priv->video_streams, title->value); mp_msg(MSGT_DEMUX,MSGL_DBG2,"aspect= %d*%d/(%d*%d)\n", codec->width, codec->sample_aspect_ratio.num, codec->height, codec->sample_aspect_ratio.den); sh_video->ds= demuxer->video; if(codec->extradata_size) memcpy(sh_video->bih + 1, codec->extradata, codec->extradata_size); if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V); /* short biPlanes; int biXPelsPerMeter; int biYPelsPerMeter; int biClrUsed; int biClrImportant; */ // select the first video stream if auto-selection is requested if(demuxer->video->id == -1) { demuxer->video->id = i; demuxer->video->sh= demuxer->v_streams[i]; } if(demuxer->video->id != i) st->discard= AVDISCARD_ALL; stream_id = priv->video_streams++; break; } case AVMEDIA_TYPE_SUBTITLE:{ sh_sub_t* sh_sub; char type; if(codec->codec_id == CODEC_ID_TEXT || codec->codec_id == AV_CODEC_ID_SUBRIP) type = 't'; else if(codec->codec_id == CODEC_ID_MOV_TEXT) type = 'm'; else if(codec->codec_id == CODEC_ID_SSA) type = 'a'; else if(codec->codec_id == CODEC_ID_DVD_SUBTITLE) type = 'v'; else if(codec->codec_id == CODEC_ID_XSUB) type = 'x'; else if(codec->codec_id == CODEC_ID_DVB_SUBTITLE) type = 'b'; else if(codec->codec_id == CODEC_ID_DVB_TELETEXT) type = 'd'; else if(codec->codec_id == CODEC_ID_HDMV_PGS_SUBTITLE) type = 'p'; #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 14, 100) else if(codec->codec_id == CODEC_ID_EIA_608) type = 'c'; #endif else if(codec->codec_tag == MKTAG('c', '6', '0', '8')) type = 'c'; else break; sh_sub = new_sh_sub_sid(demuxer, i, priv->sub_streams, lang ? lang->value : NULL); if(!sh_sub) break; stream_type = "subtitle"; priv->sstreams[priv->sub_streams] = i; sh_sub->type = type; if (codec->extradata_size) { sh_sub->extradata = malloc(codec->extradata_size); memcpy(sh_sub->extradata, codec->extradata, codec->extradata_size); sh_sub->extradata_len = codec->extradata_size; } if (title && title->value) mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_NAME=%s\n", priv->sub_streams, title->value); if (st->disposition & AV_DISPOSITION_DEFAULT) sh_sub->default_track = 1; stream_id = priv->sub_streams++; break; } case AVMEDIA_TYPE_ATTACHMENT:{ if (st->codec->codec_id == CODEC_ID_TTF) { AVDictionaryEntry *fnametag = av_dict_get(st->metadata, "filename", NULL, 0); demuxer_add_attachment(demuxer, fnametag ? fnametag->value : NULL, "application/x-truetype-font", codec->extradata, codec->extradata_size); } break; } default: st->discard= AVDISCARD_ALL; } if (stream_type) { AVCodec *avc = avcodec_find_decoder(codec->codec_id); const char *codec_name = avc ? avc->name : "unknown"; if (!avc && *stream_type == 's' && demuxer->s_streams[i]) codec_name = sh_sub_type2str(((sh_sub_t *)demuxer->s_streams[i])->type); mp_msg(MSGT_DEMUX, MSGL_INFO, "[lavf] stream %d: %s (%s), -%cid %d", i, stream_type, codec_name, *stream_type, stream_id); if (lang && lang->value && *stream_type != 'v') mp_msg(MSGT_DEMUX, MSGL_INFO, ", -%clang %s", *stream_type, lang->value); if (title && title->value) mp_msg(MSGT_DEMUX, MSGL_INFO, ", %s", title->value); mp_msg(MSGT_DEMUX, MSGL_INFO, "\n"); } }
/* "user interface" functions */ static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_output) { char buf[256]; int flags = (is_output ? ic->oformat->flags : ic->iformat->flags); AVStream *st = ic->streams[i]; int g = av_gcd(st->time_base.num, st->time_base.den); AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0); avcodec_string(buf, sizeof(buf), st->codec, is_output); av_log(NULL, AV_LOG_INFO, " Stream #%d:%d", index, i); /* the pid is an important information, so we display it */ /* XXX: add a generic system */ if (flags & AVFMT_SHOW_IDS) av_log(NULL, AV_LOG_INFO, "[0x%x]", st->id); if (lang) av_log(NULL, AV_LOG_INFO, "(%s)", lang->value); av_log(NULL, AV_LOG_DEBUG, ", %d, %d/%d", st->codec_info_nb_frames, st->time_base.num / g, st->time_base.den / g); av_log(NULL, AV_LOG_INFO, ": %s", buf); if (st->sample_aspect_ratio.num && // default av_cmp_q(st->sample_aspect_ratio, st->codec->sample_aspect_ratio)) { AVRational display_aspect_ratio; av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den, st->codec->width * st->sample_aspect_ratio.num, st->codec->height * st->sample_aspect_ratio.den, 1024 * 1024); av_log(NULL, AV_LOG_INFO, ", SAR %d:%d DAR %d:%d", st->sample_aspect_ratio.num, st->sample_aspect_ratio.den, display_aspect_ratio.num, display_aspect_ratio.den); } if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { if (st->avg_frame_rate.den && st->avg_frame_rate.num) print_fps(av_q2d(st->avg_frame_rate), "fps"); #if FF_API_R_FRAME_RATE if (st->r_frame_rate.den && st->r_frame_rate.num) print_fps(av_q2d(st->r_frame_rate), "tbr"); #endif if (st->time_base.den && st->time_base.num) print_fps(1 / av_q2d(st->time_base), "tbn"); if (st->codec->time_base.den && st->codec->time_base.num) print_fps(1 / av_q2d(st->codec->time_base), "tbc"); } if (st->disposition & AV_DISPOSITION_DEFAULT) av_log(NULL, AV_LOG_INFO, " (default)"); if (st->disposition & AV_DISPOSITION_DUB) av_log(NULL, AV_LOG_INFO, " (dub)"); if (st->disposition & AV_DISPOSITION_ORIGINAL) av_log(NULL, AV_LOG_INFO, " (original)"); if (st->disposition & AV_DISPOSITION_COMMENT) av_log(NULL, AV_LOG_INFO, " (comment)"); if (st->disposition & AV_DISPOSITION_LYRICS) av_log(NULL, AV_LOG_INFO, " (lyrics)"); if (st->disposition & AV_DISPOSITION_KARAOKE) av_log(NULL, AV_LOG_INFO, " (karaoke)"); if (st->disposition & AV_DISPOSITION_FORCED) av_log(NULL, AV_LOG_INFO, " (forced)"); if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED) av_log(NULL, AV_LOG_INFO, " (hearing impaired)"); if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED) av_log(NULL, AV_LOG_INFO, " (visual impaired)"); if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS) av_log(NULL, AV_LOG_INFO, " (clean effects)"); av_log(NULL, AV_LOG_INFO, "\n"); dump_metadata(NULL, st->metadata, " "); dump_sidedata(NULL, st, " "); }
/* returns the size or -1 on error */ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) { int bps, blkalign, bytespersec; int hdrsize = 18; int waveformatextensible; uint8_t temp[256]; uint8_t *riff_extradata= temp; uint8_t *riff_extradata_start= temp; if(!enc->codec_tag || enc->codec_tag > 0xffff) return -1; waveformatextensible = (enc->channels > 2 && enc->channel_layout) || enc->sample_rate > 48000 || av_get_bits_per_sample(enc->codec_id) > 16; if (waveformatextensible) { avio_wl16(pb, 0xfffe); } else { avio_wl16(pb, enc->codec_tag); } avio_wl16(pb, enc->channels); avio_wl32(pb, enc->sample_rate); if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3 || enc->codec_id == CODEC_ID_GSM_MS) { bps = 0; } else { if (!(bps = av_get_bits_per_sample(enc->codec_id))) { if (enc->bits_per_coded_sample) bps = enc->bits_per_coded_sample; else bps = 16; // default to 16 } } if(bps != enc->bits_per_coded_sample && enc->bits_per_coded_sample){ av_log(enc, AV_LOG_WARNING, "requested bits_per_coded_sample (%d) and actually stored (%d) differ\n", enc->bits_per_coded_sample, bps); } if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3) { blkalign = enc->frame_size; //this is wrong, but it seems many demuxers do not work if this is set correctly //blkalign = 144 * enc->bit_rate/enc->sample_rate; } else if (enc->codec_id == CODEC_ID_AC3) { blkalign = 3840; //maximum bytes per frame } else if (enc->block_align != 0) { /* specified by the codec */ blkalign = enc->block_align; } else blkalign = bps * enc->channels / av_gcd(8, bps); if (enc->codec_id == CODEC_ID_PCM_U8 || enc->codec_id == CODEC_ID_PCM_S24LE || enc->codec_id == CODEC_ID_PCM_S32LE || enc->codec_id == CODEC_ID_PCM_F32LE || enc->codec_id == CODEC_ID_PCM_F64LE || enc->codec_id == CODEC_ID_PCM_S16LE) { bytespersec = enc->sample_rate * blkalign; } else { bytespersec = enc->bit_rate / 8; } avio_wl32(pb, bytespersec); /* bytes per second */ avio_wl16(pb, blkalign); /* block align */ avio_wl16(pb, bps); /* bits per sample */ if (enc->codec_id == CODEC_ID_MP3) { hdrsize += 12; bytestream_put_le16(&riff_extradata, 1); /* wID */ bytestream_put_le32(&riff_extradata, 2); /* fdwFlags */ bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */ bytestream_put_le16(&riff_extradata, 1); /* nFramesPerBlock */ bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */ } else if (enc->codec_id == CODEC_ID_MP2) { hdrsize += 22; bytestream_put_le16(&riff_extradata, 2); /* fwHeadLayer */ bytestream_put_le32(&riff_extradata, enc->bit_rate); /* dwHeadBitrate */ bytestream_put_le16(&riff_extradata, enc->channels == 2 ? 1 : 8); /* fwHeadMode */ bytestream_put_le16(&riff_extradata, 0); /* fwHeadModeExt */ bytestream_put_le16(&riff_extradata, 1); /* wHeadEmphasis */ bytestream_put_le16(&riff_extradata, 16); /* fwHeadFlags */ bytestream_put_le32(&riff_extradata, 0); /* dwPTSLow */ bytestream_put_le32(&riff_extradata, 0); /* dwPTSHigh */ } else if (enc->codec_id == CODEC_ID_GSM_MS || enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) { hdrsize += 2; bytestream_put_le16(&riff_extradata, enc->frame_size); /* wSamplesPerBlock */ } else if(enc->extradata_size){ riff_extradata_start= enc->extradata; riff_extradata= enc->extradata + enc->extradata_size; hdrsize += enc->extradata_size; } if(waveformatextensible) { /* write WAVEFORMATEXTENSIBLE extensions */ hdrsize += 22; avio_wl16(pb, riff_extradata - riff_extradata_start + 22); /* 22 is WAVEFORMATEXTENSIBLE size */ avio_wl16(pb, enc->bits_per_coded_sample); /* ValidBitsPerSample || SamplesPerBlock || Reserved */ avio_wl32(pb, enc->channel_layout); /* dwChannelMask */ avio_wl32(pb, enc->codec_tag); /* GUID + next 3 */ avio_wl32(pb, 0x00100000); avio_wl32(pb, 0xAA000080); avio_wl32(pb, 0x719B3800); } else { avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */ } avio_write(pb, riff_extradata_start, riff_extradata - riff_extradata_start); if(hdrsize&1){ hdrsize++; avio_w8(pb, 0); } return hdrsize; }
/* returns the size or -1 on error */ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags) { int bps, blkalign, bytespersec, frame_size; int hdrsize; int64_t hdrstart = avio_tell(pb); int waveformatextensible; uint8_t temp[256]; uint8_t *riff_extradata = temp; uint8_t *riff_extradata_start = temp; if (!enc->codec_tag || enc->codec_tag > 0xffff) return -1; /* We use the known constant frame size for the codec if known, otherwise * fall back on using AVCodecContext.frame_size, which is not as reliable * for indicating packet duration. */ frame_size = av_get_audio_frame_duration(enc, enc->block_align); waveformatextensible = (enc->channels > 2 && enc->channel_layout) || enc->sample_rate > 48000 || enc->codec_id == AV_CODEC_ID_EAC3 || av_get_bits_per_sample(enc->codec_id) > 16; if (waveformatextensible) avio_wl16(pb, 0xfffe); else avio_wl16(pb, enc->codec_tag); avio_wl16(pb, enc->channels); avio_wl32(pb, enc->sample_rate); if (enc->codec_id == AV_CODEC_ID_ATRAC3 || enc->codec_id == AV_CODEC_ID_G723_1 || enc->codec_id == AV_CODEC_ID_MP2 || enc->codec_id == AV_CODEC_ID_MP3 || enc->codec_id == AV_CODEC_ID_GSM_MS) { bps = 0; } else { if (!(bps = av_get_bits_per_sample(enc->codec_id))) { if (enc->bits_per_coded_sample) bps = enc->bits_per_coded_sample; else bps = 16; // default to 16 } } if (bps != enc->bits_per_coded_sample && enc->bits_per_coded_sample) { av_log(enc, AV_LOG_WARNING, "requested bits_per_coded_sample (%d) " "and actually stored (%d) differ\n", enc->bits_per_coded_sample, bps); } if (enc->codec_id == AV_CODEC_ID_MP2) { blkalign = (144 * enc->bit_rate - 1)/enc->sample_rate + 1; } else if (enc->codec_id == AV_CODEC_ID_MP3) { blkalign = 576 * (enc->sample_rate <= (24000 + 32000)/2 ? 1 : 2); } else if (enc->codec_id == AV_CODEC_ID_AC3) { blkalign = 3840; /* maximum bytes per frame */ } else if (enc->codec_id == AV_CODEC_ID_AAC) { blkalign = 768 * enc->channels; /* maximum bytes per frame */ } else if (enc->codec_id == AV_CODEC_ID_G723_1) { blkalign = 24; } else if (enc->block_align != 0) { /* specified by the codec */ blkalign = enc->block_align; } else blkalign = bps * enc->channels / av_gcd(8, bps); if (enc->codec_id == AV_CODEC_ID_PCM_U8 || enc->codec_id == AV_CODEC_ID_PCM_S24LE || enc->codec_id == AV_CODEC_ID_PCM_S32LE || enc->codec_id == AV_CODEC_ID_PCM_F32LE || enc->codec_id == AV_CODEC_ID_PCM_F64LE || enc->codec_id == AV_CODEC_ID_PCM_S16LE) { bytespersec = enc->sample_rate * blkalign; } else if (enc->codec_id == AV_CODEC_ID_G723_1) { bytespersec = 800; } else { bytespersec = enc->bit_rate / 8; } avio_wl32(pb, bytespersec); /* bytes per second */ avio_wl16(pb, blkalign); /* block align */ avio_wl16(pb, bps); /* bits per sample */ if (enc->codec_id == AV_CODEC_ID_MP3) { bytestream_put_le16(&riff_extradata, 1); /* wID */ bytestream_put_le32(&riff_extradata, 2); /* fdwFlags */ bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */ bytestream_put_le16(&riff_extradata, 1); /* nFramesPerBlock */ bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */ } else if (enc->codec_id == AV_CODEC_ID_MP2) { /* fwHeadLayer */ bytestream_put_le16(&riff_extradata, 2); /* dwHeadBitrate */ bytestream_put_le32(&riff_extradata, enc->bit_rate); /* fwHeadMode */ bytestream_put_le16(&riff_extradata, enc->channels == 2 ? 1 : 8); /* fwHeadModeExt */ bytestream_put_le16(&riff_extradata, 0); /* wHeadEmphasis */ bytestream_put_le16(&riff_extradata, 1); /* fwHeadFlags */ bytestream_put_le16(&riff_extradata, 16); /* dwPTSLow */ bytestream_put_le32(&riff_extradata, 0); /* dwPTSHigh */ bytestream_put_le32(&riff_extradata, 0); } else if (enc->codec_id == AV_CODEC_ID_G723_1) { bytestream_put_le32(&riff_extradata, 0x9ace0002); /* extradata needed for msacm g723.1 codec */ bytestream_put_le32(&riff_extradata, 0xaea2f732); bytestream_put_le16(&riff_extradata, 0xacde); } else if (enc->codec_id == AV_CODEC_ID_GSM_MS || enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { /* wSamplesPerBlock */ bytestream_put_le16(&riff_extradata, frame_size); } else if (enc->extradata_size) { riff_extradata_start = enc->extradata; riff_extradata = enc->extradata + enc->extradata_size; } /* write WAVEFORMATEXTENSIBLE extensions */ if (waveformatextensible) { int write_channel_mask = enc->strict_std_compliance < FF_COMPLIANCE_NORMAL || enc->channel_layout < 0x40000; /* 22 is WAVEFORMATEXTENSIBLE size */ avio_wl16(pb, riff_extradata - riff_extradata_start + 22); /* ValidBitsPerSample || SamplesPerBlock || Reserved */ avio_wl16(pb, bps); /* dwChannelMask */ avio_wl32(pb, write_channel_mask ? enc->channel_layout : 0); /* GUID + next 3 */ if (enc->codec_id == AV_CODEC_ID_EAC3) { ff_put_guid(pb, ff_get_codec_guid(enc->codec_id, ff_codec_wav_guids)); } else { avio_wl32(pb, enc->codec_tag); avio_wl32(pb, 0x00100000); avio_wl32(pb, 0xAA000080); avio_wl32(pb, 0x719B3800); } } else if ((flags & FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX) || enc->codec_tag != 0x0001 /* PCM */ || riff_extradata - riff_extradata_start) { /* WAVEFORMATEX */ avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */ } /* else PCMWAVEFORMAT */ avio_write(pb, riff_extradata_start, riff_extradata - riff_extradata_start); hdrsize = avio_tell(pb) - hdrstart; if (hdrsize & 1) { hdrsize++; avio_w8(pb, 0); } return hdrsize; }
static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i) { lavf_priv_t *priv= demuxer->priv; AVStream *st= avfc->streams[i]; AVCodecContext *codec= st->codec; char *stream_type = NULL; int stream_id; AVMetadataTag *lang = av_metadata_get(st->metadata, "language", NULL, 0); AVMetadataTag *title= av_metadata_get(st->metadata, "title", NULL, 0); int g, override_tag = av_codec_get_tag(mp_codecid_override_taglists, codec->codec_id); // For some formats (like PCM) always trust CODEC_ID_* more than codec_tag if (override_tag) codec->codec_tag = override_tag; switch(codec->codec_type){ case CODEC_TYPE_AUDIO:{ WAVEFORMATEX *wf; sh_audio_t* sh_audio; sh_audio = new_sh_audio_aid(demuxer, i, priv->audio_streams, lang ? lang->value : NULL); if(!sh_audio) break; stream_type = "audio"; priv->astreams[priv->audio_streams] = i; wf= calloc(sizeof(WAVEFORMATEX) + codec->extradata_size, 1); // mp4a tag is used for all mp4 files no matter what they actually contain if(codec->codec_tag == MKTAG('m', 'p', '4', 'a')) codec->codec_tag= 0; if(!codec->codec_tag) codec->codec_tag= av_codec_get_tag(mp_wav_taglists, codec->codec_id); wf->wFormatTag= codec->codec_tag; wf->nChannels= codec->channels; wf->nSamplesPerSec= codec->sample_rate; wf->nAvgBytesPerSec= codec->bit_rate/8; wf->nBlockAlign= codec->block_align ? codec->block_align : 1; wf->wBitsPerSample= codec->bits_per_coded_sample; wf->cbSize= codec->extradata_size; if(codec->extradata_size) memcpy(wf + 1, codec->extradata, codec->extradata_size); sh_audio->wf= wf; sh_audio->audio.dwSampleSize= codec->block_align; if(codec->frame_size && codec->sample_rate){ sh_audio->audio.dwScale=codec->frame_size; sh_audio->audio.dwRate= codec->sample_rate; }else{ sh_audio->audio.dwScale= codec->block_align ? codec->block_align*8 : 8; sh_audio->audio.dwRate = codec->bit_rate; } g= av_gcd(sh_audio->audio.dwScale, sh_audio->audio.dwRate); sh_audio->audio.dwScale /= g; sh_audio->audio.dwRate /= g; // printf("sca:%d rat:%d fs:%d sr:%d ba:%d\n", sh_audio->audio.dwScale, sh_audio->audio.dwRate, codec->frame_size, codec->sample_rate, codec->block_align); sh_audio->ds= demuxer->audio; sh_audio->format= codec->codec_tag; sh_audio->channels= codec->channels; sh_audio->samplerate= codec->sample_rate; /* in opencore : try_decode_frame() delete in libavformat/utils.c ,so some parame maybe not be get so if samplerate no get in header, then give a fix value 44100 */ if(!sh_audio->channels) sh_audio->channels = 2; if(!sh_audio->samplerate) sh_audio->samplerate = 44100; sh_audio->i_bps= codec->bit_rate/8; switch (codec->codec_id) { case CODEC_ID_PCM_S8: case CODEC_ID_PCM_U8: sh_audio->samplesize = 1; break; case CODEC_ID_PCM_S16LE: case CODEC_ID_PCM_S16BE: case CODEC_ID_PCM_U16LE: case CODEC_ID_PCM_U16BE: sh_audio->samplesize = 2; break; case CODEC_ID_PCM_ALAW: sh_audio->format = 0x6; break; case CODEC_ID_PCM_MULAW: sh_audio->format = 0x7; break; } if (title && title->value) mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_NAME=%s\n", priv->audio_streams, title->value); if (st->disposition & AV_DISPOSITION_DEFAULT) sh_audio->default_track = 1; if(mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_audio->wf, MSGL_V); // select the first audio stream if (!demuxer->audio->sh) { demuxer->audio->id = i; demuxer->audio->sh= demuxer->a_streams[i]; } else st->discard= AVDISCARD_ALL; stream_id = priv->audio_streams++; break; } case CODEC_TYPE_VIDEO:{ sh_video_t* sh_video; BITMAPINFOHEADER *bih; sh_video=new_sh_video_vid(demuxer, i, priv->video_streams); if(!sh_video) break; stream_type = "video"; priv->vstreams[priv->video_streams] = i; bih=calloc(sizeof(BITMAPINFOHEADER) + codec->extradata_size,1); if(codec->codec_id == CODEC_ID_RAWVIDEO) { switch (codec->pix_fmt) { case PIX_FMT_RGB24: codec->codec_tag= MKTAG(24, 'B', 'G', 'R'); } } if(!codec->codec_tag) codec->codec_tag= av_codec_get_tag(mp_bmp_taglists, codec->codec_id); bih->biSize= sizeof(BITMAPINFOHEADER) + codec->extradata_size; if(!codec->width || !codec->height){ codec->width = 16*4; codec->height = 9*4; } bih->biWidth= codec->width; bih->biHeight= codec->height; bih->biBitCount= codec->bits_per_coded_sample; bih->biSizeImage = bih->biWidth * bih->biHeight * bih->biBitCount/8; bih->biCompression= codec->codec_tag; sh_video->bih= bih; sh_video->disp_w= codec->width; sh_video->disp_h= codec->height; if (st->time_base.den) { /* if container has time_base, use that */ sh_video->video.dwRate= st->time_base.den; sh_video->video.dwScale= st->time_base.num; } else { sh_video->video.dwRate= codec->time_base.den; sh_video->video.dwScale= codec->time_base.num; } sh_video->fps=av_q2d(st->r_frame_rate); sh_video->frametime=1/av_q2d(st->r_frame_rate); sh_video->format=bih->biCompression; if(st->sample_aspect_ratio.num) sh_video->aspect = codec->width * st->sample_aspect_ratio.num / (float)(codec->height * st->sample_aspect_ratio.den); else sh_video->aspect=codec->width * codec->sample_aspect_ratio.num / (float)(codec->height * codec->sample_aspect_ratio.den); sh_video->rotation_degrees = st->rotation_degrees; sh_video->i_bps=codec->bit_rate/8; if (title && title->value) mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VID_%d_NAME=%s\n", priv->video_streams, title->value); mp_msg(MSGT_DEMUX,MSGL_DBG2,"aspect= %d*%d/(%d*%d)\n", codec->width, codec->sample_aspect_ratio.num, codec->height, codec->sample_aspect_ratio.den); sh_video->ds= demuxer->video; if(codec->extradata_size) memcpy(sh_video->bih + 1, codec->extradata, codec->extradata_size); if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V); /* short biPlanes; int biXPelsPerMeter; int biYPelsPerMeter; int biClrUsed; int biClrImportant; */ if(demuxer->video->id != i && demuxer->video->id != -1) st->discard= AVDISCARD_ALL; else{ demuxer->video->id = i; demuxer->video->sh= demuxer->v_streams[i]; } stream_id = priv->video_streams++; break; } case CODEC_TYPE_SUBTITLE:{ sh_sub_t* sh_sub; char type; /* only support text subtitles for now */ if(codec->codec_id == CODEC_ID_TEXT) type = 't'; else if(codec->codec_id == CODEC_ID_MOV_TEXT) type = 'm'; else if(codec->codec_id == CODEC_ID_SSA) type = 'a'; else if(codec->codec_id == CODEC_ID_DVD_SUBTITLE) type = 'v'; else if(codec->codec_id == CODEC_ID_XSUB) type = 'x'; else if(codec->codec_id == CODEC_ID_DVB_SUBTITLE) type = 'b'; else if(codec->codec_id == CODEC_ID_DVB_TELETEXT) type = 'd'; else if(codec->codec_id == CODEC_ID_HDMV_PGS_SUBTITLE) type = 'p'; else break; sh_sub = new_sh_sub_sid(demuxer, i, priv->sub_streams, lang ? lang->value : NULL); if(!sh_sub) break; stream_type = "subtitle"; priv->sstreams[priv->sub_streams] = i; sh_sub->type = type; if (codec->extradata_size) { sh_sub->extradata = malloc(codec->extradata_size); memcpy(sh_sub->extradata, codec->extradata, codec->extradata_size); sh_sub->extradata_len = codec->extradata_size; } if (title && title->value) mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_NAME=%s\n", priv->sub_streams, title->value); if (st->disposition & AV_DISPOSITION_DEFAULT) sh_sub->default_track = 1; stream_id = priv->sub_streams++; break; } case CODEC_TYPE_ATTACHMENT:{ if (st->codec->codec_id == CODEC_ID_TTF) demuxer_add_attachment(demuxer, st->filename, "application/x-truetype-font", codec->extradata, codec->extradata_size); break; } default: st->discard= AVDISCARD_ALL; } if (stream_type) { AVCodec *avc = avcodec_find_decoder(codec->codec_id); const char *codec_name = avc ? avc->name : "unknown"; if (strcmp("tta", codec_name) == 0) demuxer->ttaflag = 1; if (!avc && *stream_type == 's' && demuxer->s_streams[stream_id]) codec_name = sh_sub_type2str(((sh_sub_t *)demuxer->s_streams[stream_id])->type); mp_msg(MSGT_DEMUX, MSGL_INFO, "[lavf] stream %d: %s (%s), -%cid %d", i, stream_type, codec_name, *stream_type, stream_id); if (lang && lang->value && *stream_type != 'v') mp_msg(MSGT_DEMUX, MSGL_INFO, ", -%clang %s", *stream_type, lang->value); if (title && title->value) mp_msg(MSGT_DEMUX, MSGL_INFO, ", %s", title->value); mp_msg(MSGT_DEMUX, MSGL_INFO, "\n"); } }
int main(void) { AVRational a,b,r; for (a.num = -2; a.num <= 2; a.num++) { for (a.den = -2; a.den <= 2; a.den++) { for (b.num = -2; b.num <= 2; b.num++) { for (b.den = -2; b.den <= 2; b.den++) { int c = av_cmp_q(a,b); double d = av_q2d(a) == av_q2d(b) ? 0 : (av_q2d(a) - av_q2d(b)); if (d > 0) d = 1; else if (d < 0) d = -1; else if (d != d) d = INT_MIN; if (c != d) av_log(NULL, AV_LOG_ERROR, "%d/%d %d/%d, %d %f\n", a.num, a.den, b.num, b.den, c,d); r = av_sub_q(av_add_q(b,a), b); if(b.den && (r.num*a.den != a.num*r.den || !r.num != !a.num || !r.den != !a.den)) av_log(NULL, AV_LOG_ERROR, "%d/%d ", r.num, r.den); } } } } for (a.num = 1; a.num <= 10; a.num++) { for (a.den = 1; a.den <= 10; a.den++) { if (av_gcd(a.num, a.den) > 1) continue; for (b.num = 1; b.num <= 10; b.num++) { for (b.den = 1; b.den <= 10; b.den++) { int start; if (av_gcd(b.num, b.den) > 1) continue; if (av_cmp_q(b, a) < 0) continue; for (start = 0; start < 10 ; start++) { int acc= start; int i; for (i = 0; i<100; i++) { int exact = start + av_rescale_q(i+1, b, a); acc = av_add_stable(a, acc, b, 1); if (FFABS(acc - exact) > 2) { av_log(NULL, AV_LOG_ERROR, "%d/%d %d/%d, %d %d\n", a.num, a.den, b.num, b.den, acc, exact); return 1; } } } } } } } for (a.den = 1; a.den < 0x100000000U/3; a.den*=3) { for (a.num = -1; a.num < (1<<27); a.num += 1 + a.num/100) { float f = av_int2float(av_q2intfloat(a)); float f2 = av_q2d(a); if (fabs(f - f2) > fabs(f)/5000000) { av_log(NULL, AV_LOG_ERROR, "%d/%d %f %f\n", a.num, a.den, f, f2); return 1; } } } return 0; }
/* returns the size or -1 on error */ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) { int bps, blkalign, bytespersec, frame_size; int hdrsize = 18; int waveformatextensible; uint8_t temp[256]; uint8_t *riff_extradata = temp; uint8_t *riff_extradata_start = temp; if (!enc->codec_tag || enc->codec_tag > 0xffff) return -1; /* We use the known constant frame size for the codec if known, otherwise * fall back on using AVCodecContext.frame_size, which is not as reliable * for indicating packet duration. */ frame_size = av_get_audio_frame_duration(enc, enc->block_align); waveformatextensible = (enc->channels > 2 && enc->channel_layout) || enc->sample_rate > 48000 || av_get_bits_per_sample(enc->codec_id) > 16; if (waveformatextensible) avio_wl16(pb, 0xfffe); else avio_wl16(pb, enc->codec_tag); avio_wl16(pb, enc->channels); avio_wl32(pb, enc->sample_rate); if (enc->codec_id == AV_CODEC_ID_MP2 || enc->codec_id == AV_CODEC_ID_MP3 || enc->codec_id == AV_CODEC_ID_GSM_MS) { bps = 0; } else { if (!(bps = av_get_bits_per_sample(enc->codec_id))) { if (enc->bits_per_coded_sample) bps = enc->bits_per_coded_sample; else bps = 16; // default to 16 } } if (bps != enc->bits_per_coded_sample && enc->bits_per_coded_sample) { av_log(enc, AV_LOG_WARNING, "requested bits_per_coded_sample (%d) " "and actually stored (%d) differ\n", enc->bits_per_coded_sample, bps); } if (enc->codec_id == AV_CODEC_ID_MP2) { blkalign = frame_size; } else if (enc->codec_id == AV_CODEC_ID_MP3) { blkalign = 576 * (enc->sample_rate <= 24000 ? 1 : 2); } else if (enc->codec_id == AV_CODEC_ID_AC3) { blkalign = 3840; /* maximum bytes per frame */ } else if (enc->block_align != 0) { /* specified by the codec */ blkalign = enc->block_align; } else blkalign = bps * enc->channels / av_gcd(8, bps); if (enc->codec_id == AV_CODEC_ID_PCM_U8 || enc->codec_id == AV_CODEC_ID_PCM_S24LE || enc->codec_id == AV_CODEC_ID_PCM_S32LE || enc->codec_id == AV_CODEC_ID_PCM_F32LE || enc->codec_id == AV_CODEC_ID_PCM_F64LE || enc->codec_id == AV_CODEC_ID_PCM_S16LE) { bytespersec = enc->sample_rate * blkalign; } else { bytespersec = enc->bit_rate / 8; } avio_wl32(pb, bytespersec); /* bytes per second */ avio_wl16(pb, blkalign); /* block align */ avio_wl16(pb, bps); /* bits per sample */ if (enc->codec_id == AV_CODEC_ID_MP3) { hdrsize += 12; bytestream_put_le16(&riff_extradata, 1); /* wID */ bytestream_put_le32(&riff_extradata, 2); /* fdwFlags */ bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */ bytestream_put_le16(&riff_extradata, 1); /* nFramesPerBlock */ bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */ } else if (enc->codec_id == AV_CODEC_ID_MP2) { hdrsize += 22; /* fwHeadLayer */ bytestream_put_le16(&riff_extradata, 2); /* dwHeadBitrate */ bytestream_put_le32(&riff_extradata, enc->bit_rate); /* fwHeadMode */ bytestream_put_le16(&riff_extradata, enc->channels == 2 ? 1 : 8); /* fwHeadModeExt */ bytestream_put_le16(&riff_extradata, 0); /* wHeadEmphasis */ bytestream_put_le16(&riff_extradata, 1); /* fwHeadFlags */ bytestream_put_le16(&riff_extradata, 16); /* dwPTSLow */ bytestream_put_le32(&riff_extradata, 0); /* dwPTSHigh */ bytestream_put_le32(&riff_extradata, 0); } else if (enc->codec_id == AV_CODEC_ID_GSM_MS || enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { hdrsize += 2; /* wSamplesPerBlock */ bytestream_put_le16(&riff_extradata, frame_size); } else if (enc->extradata_size) { riff_extradata_start = enc->extradata; riff_extradata = enc->extradata + enc->extradata_size; hdrsize += enc->extradata_size; } /* write WAVEFORMATEXTENSIBLE extensions */ if (waveformatextensible) { hdrsize += 22; /* 22 is WAVEFORMATEXTENSIBLE size */ avio_wl16(pb, riff_extradata - riff_extradata_start + 22); /* ValidBitsPerSample || SamplesPerBlock || Reserved */ avio_wl16(pb, bps); /* dwChannelMask */ avio_wl32(pb, enc->channel_layout); /* GUID + next 3 */ avio_wl32(pb, enc->codec_tag); avio_wl32(pb, 0x00100000); avio_wl32(pb, 0xAA000080); avio_wl32(pb, 0x719B3800); } else { avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */ } avio_write(pb, riff_extradata_start, riff_extradata - riff_extradata_start); if (hdrsize & 1) { hdrsize++; avio_w8(pb, 0); } return hdrsize; }
int main(void) { AVRational a,b,r; int i,j,k; static const int64_t numlist[] = { INT64_MIN, INT64_MIN+1, INT64_MAX, INT32_MIN, INT32_MAX, 1,0,-1, 123456789, INT32_MAX-1, INT32_MAX+1LL, UINT32_MAX-1, UINT32_MAX, UINT32_MAX+1LL }; for (a.num = -2; a.num <= 2; a.num++) { for (a.den = -2; a.den <= 2; a.den++) { for (b.num = -2; b.num <= 2; b.num++) { for (b.den = -2; b.den <= 2; b.den++) { int c = av_cmp_q(a,b); double d = av_q2d(a) == av_q2d(b) ? 0 : (av_q2d(a) - av_q2d(b)); if (d > 0) d = 1; else if (d < 0) d = -1; else if (d != d) d = INT_MIN; if (c != d) av_log(NULL, AV_LOG_ERROR, "%d/%d %d/%d, %d %f\n", a.num, a.den, b.num, b.den, c,d); r = av_sub_q(av_add_q(b,a), b); if(b.den && (r.num*a.den != a.num*r.den || !r.num != !a.num || !r.den != !a.den)) av_log(NULL, AV_LOG_ERROR, "%d/%d ", r.num, r.den); } } } } for (i = 0; i < FF_ARRAY_ELEMS(numlist); i++) { int64_t a = numlist[i]; for (j = 0; j < FF_ARRAY_ELEMS(numlist); j++) { int64_t b = numlist[j]; if (b<=0) continue; for (k = 0; k < FF_ARRAY_ELEMS(numlist); k++) { int64_t c = numlist[k]; int64_t res; AVInteger ai; if (c<=0) continue; res = av_rescale_rnd(a,b,c, AV_ROUND_ZERO); ai = av_mul_i(av_int2i(a), av_int2i(b)); ai = av_div_i(ai, av_int2i(c)); if (av_cmp_i(ai, av_int2i(INT64_MAX)) > 0 && res == INT64_MIN) continue; if (av_cmp_i(ai, av_int2i(INT64_MIN)) < 0 && res == INT64_MIN) continue; if (av_cmp_i(ai, av_int2i(res)) == 0) continue; // Special exception for INT64_MIN, remove this in case INT64_MIN is handled without off by 1 error if (av_cmp_i(ai, av_int2i(res-1)) == 0 && a == INT64_MIN) continue; av_log(NULL, AV_LOG_ERROR, "%"PRId64" * %"PRId64" / %"PRId64" = %"PRId64" or %"PRId64"\n", a,b,c, res, av_i2int(ai)); } } } for (a.num = 1; a.num <= 10; a.num++) { for (a.den = 1; a.den <= 10; a.den++) { if (av_gcd(a.num, a.den) > 1) continue; for (b.num = 1; b.num <= 10; b.num++) { for (b.den = 1; b.den <= 10; b.den++) { int start; if (av_gcd(b.num, b.den) > 1) continue; if (av_cmp_q(b, a) < 0) continue; for (start = 0; start < 10 ; start++) { int acc= start; int i; for (i = 0; i<100; i++) { int exact = start + av_rescale_q(i+1, b, a); acc = av_add_stable(a, acc, b, 1); if (FFABS(acc - exact) > 2) { av_log(NULL, AV_LOG_ERROR, "%d/%d %d/%d, %d %d\n", a.num, a.den, b.num, b.den, acc, exact); return 1; } } } } } } } for (a.den = 1; a.den < 0x100000000U/3; a.den*=3) { for (a.num = -1; a.num < (1<<27); a.num += 1 + a.num/100) { float f = av_int2float(av_q2intfloat(a)); float f2 = av_q2d(a); if (fabs(f - f2) > fabs(f)/5000000) { av_log(NULL, AV_LOG_ERROR, "%d/%d %f %f\n", a.num, a.den, f, f2); return 1; } } } return 0; }