int MovieDecoder::getOrientation() { int32_t* matrix = reinterpret_cast<int32_t*>(av_stream_get_side_data(m_pVideoStream, AV_PKT_DATA_DISPLAYMATRIX, nullptr)); if (matrix) return lround(av_display_rotation_get(matrix)); return -1; }
double get_rotation(AVStream *st) { AVDictionaryEntry *rotate_tag = av_dict_get(st->metadata, "rotate", NULL, 0); uint8_t *displaymatrix = av_stream_get_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, NULL); double theta = 0; if (rotate_tag && *rotate_tag->value && strcmp(rotate_tag->value, "0")) { char *tail; theta = av_strtod(rotate_tag->value, &tail); if (*tail) theta = 0; } if (displaymatrix && !theta) theta = -av_display_rotation_get((int32_t *) displaymatrix); theta -= 360 * floor(theta / 360 + 0.9 / 360); if (fabs(theta - 90 * round(theta / 90)) > 2) ALOGI("Odd rotation angle.\n" "If you want to help, upload a sample " "of this file to ftp://upload.ffmpeg.org/incoming/ " "and contact the ffmpeg-devel mailing list. ([email protected])"); return theta; }
static void mp3_update_xing(AVFormatContext *s) { MP3Context *mp3 = s->priv_data; AVReplayGain *rg; uint16_t tag_crc; uint8_t *toc; int i, rg_size; /* replace "Xing" identification string with "Info" for CBR files. */ if (!mp3->has_variable_bitrate) AV_WL32(mp3->xing_frame + mp3->xing_offset, MKTAG('I', 'n', 'f', 'o')); AV_WB32(mp3->xing_frame + mp3->xing_offset + 8, mp3->frames); AV_WB32(mp3->xing_frame + mp3->xing_offset + 12, mp3->size); toc = mp3->xing_frame + mp3->xing_offset + 16; toc[0] = 0; // first toc entry has to be zero. for (i = 1; i < XING_TOC_SIZE; ++i) { int j = i * mp3->pos / XING_TOC_SIZE; int seek_point = 256LL * mp3->bag[j] / mp3->size; toc[i] = FFMIN(seek_point, 255); } /* write replaygain */ rg = (AVReplayGain*)av_stream_get_side_data(s->streams[0], AV_PKT_DATA_REPLAYGAIN, &rg_size); if (rg && rg_size >= sizeof(*rg)) { uint16_t val; AV_WB32(mp3->xing_frame + mp3->xing_offset + 131, av_rescale(rg->track_peak, 1 << 23, 100000)); if (rg->track_gain != INT32_MIN) { val = FFABS(rg->track_gain / 10000) & ((1 << 9) - 1); val |= (rg->track_gain < 0) << 9; val |= 1 << 13; AV_WB16(mp3->xing_frame + mp3->xing_offset + 135, val); } if (rg->album_gain != INT32_MIN) { val = FFABS(rg->album_gain / 10000) & ((1 << 9) - 1); val |= (rg->album_gain < 0) << 9; val |= 1 << 14; AV_WB16(mp3->xing_frame + mp3->xing_offset + 137, val); } } AV_WB32(mp3->xing_frame + mp3->xing_offset + XING_SIZE - 8, mp3->audio_size); AV_WB16(mp3->xing_frame + mp3->xing_offset + XING_SIZE - 4, mp3->audio_crc); tag_crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI_LE), 0, mp3->xing_frame, 190); AV_WB16(mp3->xing_frame + mp3->xing_offset + XING_SIZE - 2, tag_crc); avio_seek(s->pb, mp3->xing_frame_offset, SEEK_SET); avio_write(s->pb, mp3->xing_frame, mp3->xing_frame_size); avio_seek(s->pb, 0, SEEK_END); }
double sxpi_demuxing_probe_rotation(const struct demuxing_ctx *ctx) { AVStream *st = (AVStream *)ctx->stream; // XXX: Fix FFmpeg. AVDictionaryEntry *rotate_tag = av_dict_get(st->metadata, "rotate", NULL, 0); const uint8_t *displaymatrix = av_stream_get_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, NULL); double theta = 0; if (rotate_tag && *rotate_tag->value && strcmp(rotate_tag->value, "0")) { char *tail; theta = av_strtod(rotate_tag->value, &tail); if (*tail) theta = 0; } if (displaymatrix && !theta) theta = -av_display_rotation_get((const int32_t *)displaymatrix); theta -= 360*floor(theta/360 + 0.9/360); return theta; }
int32_t MovieDecoder::getStreamRotation() { int32_t* matrix = reinterpret_cast<int32_t*>(av_stream_get_side_data(m_pVideoStream, AV_PKT_DATA_DISPLAYMATRIX, nullptr)); if (matrix) { auto angle = lround(av_display_rotation_get(matrix)); if (angle > 45 && angle < 135) { return 2; } else if (angle < -45 && angle > -135) { return 1; } } return -1; }
static void get_rotation(es_format_t *fmt, AVStream *s) { char const *kRotateKey = "rotate"; AVDictionaryEntry *rotation = av_dict_get(s->metadata, kRotateKey, NULL, 0); long angle = 0; if( rotation ) { angle = strtol(rotation->value, NULL, 10); if (angle > 45 && angle < 135) fmt->video.orientation = ORIENT_ROTATED_90; else if (angle > 135 && angle < 225) fmt->video.orientation = ORIENT_ROTATED_180; else if (angle > 225 && angle < 315) fmt->video.orientation = ORIENT_ROTATED_270; else fmt->video.orientation = ORIENT_NORMAL; } int32_t *matrix = (int32_t *)av_stream_get_side_data(s, AV_PKT_DATA_DISPLAYMATRIX, NULL); if( matrix ) { angle = lround(av_display_rotation_get(matrix)); if (angle > 45 && angle < 135) fmt->video.orientation = ORIENT_ROTATED_270; else if (angle > 135 || angle < -135) fmt->video.orientation = ORIENT_ROTATED_180; else if (angle < -45 && angle > -135) fmt->video.orientation = ORIENT_ROTATED_90; else fmt->video.orientation = ORIENT_NORMAL; } }
static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, AVFilterInOut *in) { AVFilterContext *last_filter; const AVFilter *buffer_filt = avfilter_get_by_name("buffer"); InputStream *ist = ifilter->ist; InputFile *f = input_files[ist->file_index]; AVRational tb = ist->framerate.num ? av_inv_q(ist->framerate) : ist->st->time_base; AVRational sar; char args[255], name[255]; int ret, pad_idx = 0; sar = ist->st->sample_aspect_ratio.num ? ist->st->sample_aspect_ratio : ist->dec_ctx->sample_aspect_ratio; snprintf(args, sizeof(args), "width=%d:height=%d:pix_fmt=%d:time_base=%d/%d:sar=%d/%d", ist->dec_ctx->width, ist->dec_ctx->height, ist->hwaccel_retrieve_data ? ist->hwaccel_retrieved_pix_fmt : ist->dec_ctx->pix_fmt, tb.num, tb.den, sar.num, sar.den); snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, ist->file_index, ist->st->index); if ((ret = avfilter_graph_create_filter(&ifilter->filter, buffer_filt, name, args, NULL, fg->graph)) < 0) return ret; last_filter = ifilter->filter; if (ist->autorotate) { uint8_t* displaymatrix = av_stream_get_side_data(ist->st, AV_PKT_DATA_DISPLAYMATRIX, NULL); if (displaymatrix) { double rot = av_display_rotation_get((int32_t*) displaymatrix); if (rot < -135 || rot > 135) { ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL); if (ret < 0) return ret; ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL); } else if (rot < -45) { ret = insert_filter(&last_filter, &pad_idx, "transpose", "dir=clock"); } else if (rot > 45) { ret = insert_filter(&last_filter, &pad_idx, "transpose", "dir=cclock"); } if (ret < 0) return ret; } } if (ist->framerate.num) { AVFilterContext *setpts; snprintf(name, sizeof(name), "force CFR for input from stream %d:%d", ist->file_index, ist->st->index); if ((ret = avfilter_graph_create_filter(&setpts, avfilter_get_by_name("setpts"), name, "N", NULL, fg->graph)) < 0) return ret; if ((ret = avfilter_link(last_filter, 0, setpts, 0)) < 0) return ret; last_filter = setpts; } snprintf(name, sizeof(name), "trim for input stream %d:%d", ist->file_index, ist->st->index); ret = insert_trim(((f->start_time == AV_NOPTS_VALUE) || !f->accurate_seek) ? AV_NOPTS_VALUE : 0, f->recording_time, &last_filter, &pad_idx, name); if (ret < 0) return ret; if ((ret = avfilter_link(last_filter, 0, in->filter_ctx, in->pad_idx)) < 0) return ret; return 0; }
StreamInfo *FormatContext::getStreamInfo(AVStream *stream) const { if (streamNotValid(stream)) return nullptr; StreamInfo *streamInfo = new StreamInfo; if (const AVCodec *codec = avcodec_find_decoder(stream->codecpar->codec_id)) streamInfo->codec_name = codec->name; streamInfo->must_decode = true; if (const AVCodecDescriptor *codecDescr = avcodec_descriptor_get(stream->codecpar->codec_id)) { if (codecDescr->props & AV_CODEC_PROP_TEXT_SUB) streamInfo->must_decode = false; if (streamInfo->codec_name.isEmpty()) streamInfo->codec_name = codecDescr->name; } streamInfo->bitrate = stream->codecpar->bit_rate; streamInfo->bpcs = stream->codecpar->bits_per_coded_sample; streamInfo->codec_tag = stream->codecpar->codec_tag; streamInfo->is_default = stream->disposition & AV_DISPOSITION_DEFAULT; streamInfo->time_base.num = stream->time_base.num; streamInfo->time_base.den = stream->time_base.den; streamInfo->type = (QMPlay2MediaType)stream->codecpar->codec_type; //Enumy są takie same if (stream->codecpar->extradata_size) { streamInfo->data.reserve(stream->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); streamInfo->data.resize(stream->codecpar->extradata_size); memcpy(streamInfo->data.data(), stream->codecpar->extradata, streamInfo->data.capacity()); av_free(stream->codecpar->extradata); stream->codecpar->extradata = (quint8 *)streamInfo->data.data(); } if (streamInfo->type != QMPLAY2_TYPE_ATTACHMENT) { QString value; if (streamsInfo.count() > 1) { streamInfo->title = getTag(stream->metadata, "title"); streamInfo->artist = getTag(stream->metadata, "artist"); if (!(value = getTag(stream->metadata, "album")).isEmpty()) streamInfo->other_info += {QString::number(QMPLAY2_TAG_ALBUM), value}; if (!(value = getTag(stream->metadata, "genre")).isEmpty()) streamInfo->other_info += {QString::number(QMPLAY2_TAG_GENRE), value}; if (!(value = getTag(stream->metadata, "date")).isEmpty()) streamInfo->other_info += {QString::number(QMPLAY2_TAG_DATE), value}; if (!(value = getTag(stream->metadata, "comment")).isEmpty()) streamInfo->other_info += {QString::number(QMPLAY2_TAG_COMMENT), value}; } if (!(value = getTag(stream->metadata, "language", false)).isEmpty() && value != "und") streamInfo->other_info += {QString::number(QMPLAY2_TAG_LANGUAGE), value}; } switch (streamInfo->type) { case QMPLAY2_TYPE_AUDIO: streamInfo->format = av_get_sample_fmt_name((AVSampleFormat)stream->codecpar->format); streamInfo->channels = stream->codecpar->channels; streamInfo->sample_rate = stream->codecpar->sample_rate; streamInfo->block_align = stream->codecpar->block_align; break; case QMPLAY2_TYPE_VIDEO: { streamInfo->format = av_get_pix_fmt_name((AVPixelFormat)stream->codecpar->format); if (stream->sample_aspect_ratio.num) streamInfo->sample_aspect_ratio = av_q2d(stream->sample_aspect_ratio); else if (stream->codecpar->sample_aspect_ratio.num) streamInfo->sample_aspect_ratio = av_q2d(stream->codecpar->sample_aspect_ratio); streamInfo->W = stream->codecpar->width; streamInfo->H = stream->codecpar->height; if (!stillImage) streamInfo->FPS = av_q2d(stream->r_frame_rate); bool ok = false; const double rotation = getTag(stream->metadata, "rotate", false).toDouble(&ok); if (ok) streamInfo->rotation = rotation; if (void *sideData = av_stream_get_side_data(stream, AV_PKT_DATA_SPHERICAL, nullptr)) { streamInfo->spherical = (((AVSphericalMapping *)sideData)->projection == AV_SPHERICAL_EQUIRECTANGULAR); } break; } case QMPLAY2_TYPE_ATTACHMENT: streamInfo->title = getTag(stream->metadata, "filename", false); switch (stream->codecpar->codec_id) { case AV_CODEC_ID_TTF: streamInfo->codec_name = "TTF"; break; case AV_CODEC_ID_OTF: streamInfo->codec_name = "OTF"; break; default: break; } break; default: break; } return streamInfo; }
bool FormatContext::getReplayGain(bool album, float &gain_db, float &peak) const { const int streamIdx = av_find_best_stream(formatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, nullptr, 0); if (streamIdx > -1) { if (void *sideData = av_stream_get_side_data(streams[streamIdx], AV_PKT_DATA_REPLAYGAIN, nullptr)) { AVReplayGain replayGain = *(AVReplayGain *)sideData; qint32 tmpGain; quint32 tmpPeak; if (replayGain.album_gain == INT32_MIN && replayGain.track_gain != INT32_MIN) replayGain.album_gain = replayGain.track_gain; if (replayGain.album_gain != INT32_MIN && replayGain.track_gain == INT32_MIN) replayGain.track_gain = replayGain.album_gain; if (replayGain.album_peak == 0 && replayGain.track_peak != 0) replayGain.album_peak = replayGain.track_peak; if (replayGain.album_peak != 0 && replayGain.track_peak == 0) replayGain.track_peak = replayGain.album_peak; if (album) { tmpGain = replayGain.album_gain; tmpPeak = replayGain.album_peak; } else { tmpGain = replayGain.track_gain; tmpPeak = replayGain.track_peak; } if (tmpGain == INT32_MIN) return false; gain_db = tmpGain / 100000.0; if (tmpPeak != 0) peak = tmpPeak / 100000.0; return true; } } if (AVDictionary *dict = getMetadata()) { QString album_gain_db = getTag(dict, "REPLAYGAIN_ALBUM_GAIN", false); QString album_peak = getTag(dict, "REPLAYGAIN_ALBUM_PEAK", false); QString track_gain_db = getTag(dict, "REPLAYGAIN_TRACK_GAIN", false); QString track_peak = getTag(dict, "REPLAYGAIN_TRACK_PEAK", false); if (album_gain_db.isEmpty() && !track_gain_db.isEmpty()) album_gain_db = track_gain_db; if (!album_gain_db.isEmpty() && track_gain_db.isEmpty()) track_gain_db = album_gain_db; if (album_peak.isEmpty() && !track_peak.isEmpty()) album_peak = track_peak; if (!album_peak.isEmpty() && track_peak.isEmpty()) track_peak = album_peak; QString str_gain_db, str_peak; if (album) { str_gain_db = album_gain_db; str_peak = album_peak; } else { str_gain_db = track_gain_db; str_peak = track_peak; } int space_idx = str_gain_db.indexOf(' '); if (space_idx > -1) str_gain_db.remove(space_idx, str_gain_db.length() - space_idx); bool ok; float tmp = str_peak.toFloat(&ok); if (ok) peak = tmp; tmp = str_gain_db.toFloat(&ok); if (ok) gain_db = tmp; return ok; } return false; }