mirror of https://git.videolan.org/git/ffmpeg.git
avformat/vpcc: parse bitstream data to get profile and bitdepth
Profile can be derived from values codecpar pixel format only with software formats. For hardware formats, we're forced to parse a frame header to get the required information. Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
parent
e9a67ababa
commit
cb925c0bc0
|
@ -338,7 +338,7 @@ static int init_segment_types(AVFormatContext *s)
|
||||||
static void set_vp9_codec_str(AVFormatContext *s, AVCodecParameters *par,
|
static void set_vp9_codec_str(AVFormatContext *s, AVCodecParameters *par,
|
||||||
AVRational *frame_rate, char *str, int size) {
|
AVRational *frame_rate, char *str, int size) {
|
||||||
VPCC vpcc;
|
VPCC vpcc;
|
||||||
int ret = ff_isom_get_vpcc_features(s, par, frame_rate, &vpcc);
|
int ret = ff_isom_get_vpcc_features(s, par, NULL, 0, frame_rate, &vpcc);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
av_strlcatf(str, size, "vp09.%02d.%02d.%02d",
|
av_strlcatf(str, size, "vp09.%02d.%02d.%02d",
|
||||||
vpcc.profile, vpcc.level, vpcc.bitdepth);
|
vpcc.profile, vpcc.level, vpcc.bitdepth);
|
||||||
|
|
|
@ -1375,7 +1375,8 @@ static int mov_write_vpcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra
|
||||||
ffio_wfourcc(pb, "vpcC");
|
ffio_wfourcc(pb, "vpcC");
|
||||||
avio_w8(pb, 1); /* version */
|
avio_w8(pb, 1); /* version */
|
||||||
avio_wb24(pb, 0); /* flags */
|
avio_wb24(pb, 0); /* flags */
|
||||||
ff_isom_write_vpcc(s, pb, track->par);
|
ff_isom_write_vpcc(s, pb, track->vos_data, track->vos_len, track->par);
|
||||||
|
|
||||||
return update_size(pb, pos);
|
return update_size(pb, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6033,6 +6034,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||||
if ((par->codec_id == AV_CODEC_ID_DNXHD ||
|
if ((par->codec_id == AV_CODEC_ID_DNXHD ||
|
||||||
par->codec_id == AV_CODEC_ID_H264 ||
|
par->codec_id == AV_CODEC_ID_H264 ||
|
||||||
par->codec_id == AV_CODEC_ID_HEVC ||
|
par->codec_id == AV_CODEC_ID_HEVC ||
|
||||||
|
par->codec_id == AV_CODEC_ID_VP9 ||
|
||||||
par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->vos_len &&
|
par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->vos_len &&
|
||||||
!TAG_IS_AVCI(trk->tag)) {
|
!TAG_IS_AVCI(trk->tag)) {
|
||||||
/* copy frame to create needed atoms */
|
/* copy frame to create needed atoms */
|
||||||
|
|
|
@ -22,8 +22,11 @@
|
||||||
#include "libavutil/pixdesc.h"
|
#include "libavutil/pixdesc.h"
|
||||||
#include "libavutil/pixfmt.h"
|
#include "libavutil/pixfmt.h"
|
||||||
#include "libavcodec/avcodec.h"
|
#include "libavcodec/avcodec.h"
|
||||||
|
#include "libavcodec/get_bits.h"
|
||||||
#include "vpcc.h"
|
#include "vpcc.h"
|
||||||
|
|
||||||
|
#define VP9_SYNCCODE 0x498342
|
||||||
|
|
||||||
enum VPX_CHROMA_SUBSAMPLING
|
enum VPX_CHROMA_SUBSAMPLING
|
||||||
{
|
{
|
||||||
VPX_SUBSAMPLING_420_VERTICAL = 0,
|
VPX_SUBSAMPLING_420_VERTICAL = 0,
|
||||||
|
@ -114,7 +117,41 @@ static int get_vp9_level(AVCodecParameters *par, AVRational *frame_rate) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parse_bitstream(GetBitContext *gb, int *profile, int *bit_depth) {
|
||||||
|
int keyframe, invisible;
|
||||||
|
|
||||||
|
if (get_bits(gb, 2) != 0x2) // frame marker
|
||||||
|
return;
|
||||||
|
*profile = get_bits1(gb);
|
||||||
|
*profile |= get_bits1(gb) << 1;
|
||||||
|
if (*profile == 3)
|
||||||
|
*profile += get_bits1(gb);
|
||||||
|
|
||||||
|
if (get_bits1(gb))
|
||||||
|
return;
|
||||||
|
|
||||||
|
keyframe = !get_bits1(gb);
|
||||||
|
invisible = !get_bits1(gb);
|
||||||
|
get_bits1(gb);
|
||||||
|
|
||||||
|
if (keyframe) {
|
||||||
|
if (get_bits(gb, 24) != VP9_SYNCCODE)
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
int intraonly = invisible ? get_bits1(gb) : 0;
|
||||||
|
if (!intraonly || get_bits(gb, 24) != VP9_SYNCCODE)
|
||||||
|
return;
|
||||||
|
if (*profile < 1) {
|
||||||
|
*bit_depth = 8;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*bit_depth = *profile <= 1 ? 8 : 10 + get_bits1(gb) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par,
|
int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par,
|
||||||
|
const uint8_t *data, int len,
|
||||||
AVRational *frame_rate, VPCC *vpcc)
|
AVRational *frame_rate, VPCC *vpcc)
|
||||||
{
|
{
|
||||||
int profile = par->profile;
|
int profile = par->profile;
|
||||||
|
@ -129,7 +166,17 @@ int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par,
|
||||||
if (bit_depth < 0 || vpx_chroma_subsampling < 0)
|
if (bit_depth < 0 || vpx_chroma_subsampling < 0)
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
|
|
||||||
if (profile == FF_PROFILE_UNKNOWN) {
|
if (len && (profile == FF_PROFILE_UNKNOWN || !bit_depth)) {
|
||||||
|
GetBitContext gb;
|
||||||
|
|
||||||
|
int ret = init_get_bits8(&gb, data, len);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
parse_bitstream(&gb, &profile, &bit_depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (profile == FF_PROFILE_UNKNOWN && bit_depth) {
|
||||||
if (vpx_chroma_subsampling == VPX_SUBSAMPLING_420_VERTICAL ||
|
if (vpx_chroma_subsampling == VPX_SUBSAMPLING_420_VERTICAL ||
|
||||||
vpx_chroma_subsampling == VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA) {
|
vpx_chroma_subsampling == VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA) {
|
||||||
profile = (bit_depth == 8) ? FF_PROFILE_VP9_0 : FF_PROFILE_VP9_2;
|
profile = (bit_depth == 8) ? FF_PROFILE_VP9_0 : FF_PROFILE_VP9_2;
|
||||||
|
@ -138,6 +185,9 @@ int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (profile == FF_PROFILE_UNKNOWN || !bit_depth)
|
||||||
|
av_log(s, AV_LOG_WARNING, "VP9 profile and/or bit depth not set or could not be derived\n");
|
||||||
|
|
||||||
vpcc->profile = profile;
|
vpcc->profile = profile;
|
||||||
vpcc->level = level;
|
vpcc->level = level;
|
||||||
vpcc->bitdepth = bit_depth;
|
vpcc->bitdepth = bit_depth;
|
||||||
|
@ -148,12 +198,13 @@ int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par,
|
||||||
}
|
}
|
||||||
|
|
||||||
int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb,
|
int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb,
|
||||||
|
const uint8_t *data, int len,
|
||||||
AVCodecParameters *par)
|
AVCodecParameters *par)
|
||||||
{
|
{
|
||||||
VPCC vpcc;
|
VPCC vpcc;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = ff_isom_get_vpcc_features(s, par, NULL, &vpcc);
|
ret = ff_isom_get_vpcc_features(s, par, data, len, NULL, &vpcc);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -45,14 +45,19 @@ typedef struct VPCC {
|
||||||
*
|
*
|
||||||
* @param s address of the AVFormatContext for the logging context.
|
* @param s address of the AVFormatContext for the logging context.
|
||||||
* @param pb address of the AVIOContext where the vpcC shall be written.
|
* @param pb address of the AVIOContext where the vpcC shall be written.
|
||||||
|
* @param data address of a data array which contains coded bitstream data from
|
||||||
|
* which codec information can be extracted. May be NULL.
|
||||||
|
* @param len length of the data array.
|
||||||
* @param par address of the AVCodecParameters which contains codec information.
|
* @param par address of the AVCodecParameters which contains codec information.
|
||||||
* @return >=0 in case of success, a negative value corresponding to an AVERROR
|
* @return >=0 in case of success, a negative value corresponding to an AVERROR
|
||||||
* code in case of failure
|
* code in case of failure
|
||||||
*/
|
*/
|
||||||
int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb,
|
int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb,
|
||||||
|
const uint8_t *data, int len,
|
||||||
AVCodecParameters *par);
|
AVCodecParameters *par);
|
||||||
|
|
||||||
int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par,
|
int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par,
|
||||||
|
const uint8_t *data, int len,
|
||||||
AVRational *frame_rate, VPCC *vpcc);
|
AVRational *frame_rate, VPCC *vpcc);
|
||||||
|
|
||||||
#endif /* AVFORMAT_VPCC_H */
|
#endif /* AVFORMAT_VPCC_H */
|
||||||
|
|
Loading…
Reference in New Issue