AVFormatWriter: Move codec to codecpar
* Little cleanup included.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009-2010, Stephan Aßmus <[email protected]>
|
* Copyright 2009-2010, Stephan Aßmus <[email protected]>
|
||||||
|
* Copyright 2018, Dario Casalinuovo
|
||||||
* All rights reserved. Distributed under the terms of the GNU L-GPL license.
|
* All rights reserved. Distributed under the terms of the GNU L-GPL license.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -118,30 +119,22 @@ AVFormatWriter::StreamCookie::Init(media_format* format,
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TRACE(" fStream->codec: %p\n", fStream->codec);
|
// TRACE(" fStream->codecpar: %p\n", fStream->codecpar);
|
||||||
// TODO: This is a hack for now! Use avcodec_find_encoder_by_name()
|
// TODO: This is a hack for now! Use avcodec_find_encoder_by_name()
|
||||||
// or something similar...
|
// or something similar...
|
||||||
fStream->codec->codec_id = (CodecID)codecInfo->sub_id;
|
fStream->codecpar->codec_id = (CodecID)codecInfo->sub_id;
|
||||||
if (fStream->codec->codec_id == AV_CODEC_ID_NONE)
|
if (fStream->codecpar->codec_id == AV_CODEC_ID_NONE)
|
||||||
fStream->codec->codec_id = raw_audio_codec_id_for(*format);
|
fStream->codecpar->codec_id = raw_audio_codec_id_for(*format);
|
||||||
|
|
||||||
// Setup the stream according to the media format...
|
// Setup the stream according to the media format...
|
||||||
if (format->type == B_MEDIA_RAW_VIDEO) {
|
if (format->type == B_MEDIA_RAW_VIDEO) {
|
||||||
fStream->codec->codec_type = AVMEDIA_TYPE_VIDEO;
|
fStream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||||
#if GET_CONTEXT_DEFAULTS
|
|
||||||
// NOTE: API example does not do this:
|
|
||||||
avcodec_get_context_defaults(fStream->codec);
|
|
||||||
#endif
|
|
||||||
// frame rate
|
|
||||||
fStream->codec->time_base.den = (int)format->u.raw_video.field_rate;
|
|
||||||
fStream->codec->time_base.num = 1;
|
|
||||||
|
|
||||||
fStream->time_base.den = (int)format->u.raw_video.field_rate;
|
fStream->time_base.den = (int)format->u.raw_video.field_rate;
|
||||||
fStream->time_base.num = 1;
|
fStream->time_base.num = 1;
|
||||||
|
|
||||||
// video size
|
// video size
|
||||||
fStream->codec->width = format->u.raw_video.display.line_width;
|
fStream->codecpar->width = format->u.raw_video.display.line_width;
|
||||||
fStream->codec->height = format->u.raw_video.display.line_count;
|
fStream->codecpar->height = format->u.raw_video.display.line_count;
|
||||||
// pixel aspect ratio
|
// pixel aspect ratio
|
||||||
fStream->sample_aspect_ratio.num
|
fStream->sample_aspect_ratio.num
|
||||||
= format->u.raw_video.pixel_width_aspect;
|
= format->u.raw_video.pixel_width_aspect;
|
||||||
@@ -150,51 +143,46 @@ AVFormatWriter::StreamCookie::Init(media_format* format,
|
|||||||
if (fStream->sample_aspect_ratio.num == 0
|
if (fStream->sample_aspect_ratio.num == 0
|
||||||
|| fStream->sample_aspect_ratio.den == 0) {
|
|| fStream->sample_aspect_ratio.den == 0) {
|
||||||
av_reduce(&fStream->sample_aspect_ratio.num,
|
av_reduce(&fStream->sample_aspect_ratio.num,
|
||||||
&fStream->sample_aspect_ratio.den, fStream->codec->width,
|
&fStream->sample_aspect_ratio.den, fStream->codecpar->width,
|
||||||
fStream->codec->height, 255);
|
fStream->codecpar->height, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
fStream->codec->gop_size = 12;
|
fStream->codecpar->sample_aspect_ratio = fStream->sample_aspect_ratio;
|
||||||
|
|
||||||
fStream->codec->sample_aspect_ratio = fStream->sample_aspect_ratio;
|
|
||||||
|
|
||||||
// Use the last supported pixel format of the AVCodec, which we hope
|
// Use the last supported pixel format of the AVCodec, which we hope
|
||||||
// is the one with the best quality (true for all currently supported
|
// is the one with the best quality (true for all currently supported
|
||||||
// encoders).
|
// encoders).
|
||||||
// AVCodec* codec = fStream->codec->codec;
|
// AVCodec* codec = fStream->codecpar->codec;
|
||||||
// for (int i = 0; codec->pix_fmts[i] != PIX_FMT_NONE; i++)
|
// for (int i = 0; codec->pix_fmts[i] != PIX_FMT_NONE; i++)
|
||||||
// fStream->codec->pix_fmt = codec->pix_fmts[i];
|
// fStream->codecpar->pix_fmt = codec->pix_fmts[i];
|
||||||
fStream->codec->pix_fmt = AV_PIX_FMT_YUV420P;
|
fStream->codecpar->format = AV_PIX_FMT_YUV420P;
|
||||||
|
|
||||||
} else if (format->type == B_MEDIA_RAW_AUDIO) {
|
} else if (format->type == B_MEDIA_RAW_AUDIO) {
|
||||||
fStream->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
fStream->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||||
#if GET_CONTEXT_DEFAULTS
|
|
||||||
// NOTE: API example does not do this:
|
|
||||||
avcodec_get_context_defaults(fStream->codec);
|
|
||||||
#endif
|
|
||||||
// frame rate
|
// frame rate
|
||||||
fStream->codec->sample_rate = (int)format->u.raw_audio.frame_rate;
|
fStream->codecpar->sample_rate = (int)format->u.raw_audio.frame_rate;
|
||||||
|
|
||||||
// channels
|
// channels
|
||||||
fStream->codec->channels = format->u.raw_audio.channel_count;
|
fStream->codecpar->channels = format->u.raw_audio.channel_count;
|
||||||
|
|
||||||
// set fStream to the audio format we want to use. This is only a hint
|
// set fStream to the audio format we want to use. This is only a hint
|
||||||
// (each encoder has a different set of accepted formats)
|
// (each encoder has a different set of accepted formats)
|
||||||
switch (format->u.raw_audio.format) {
|
switch (format->u.raw_audio.format) {
|
||||||
case media_raw_audio_format::B_AUDIO_FLOAT:
|
case media_raw_audio_format::B_AUDIO_FLOAT:
|
||||||
fStream->codec->sample_fmt = AV_SAMPLE_FMT_FLT;
|
fStream->codecpar->format = AV_SAMPLE_FMT_FLT;
|
||||||
break;
|
break;
|
||||||
case media_raw_audio_format::B_AUDIO_DOUBLE:
|
case media_raw_audio_format::B_AUDIO_DOUBLE:
|
||||||
fStream->codec->sample_fmt = AV_SAMPLE_FMT_DBL;
|
fStream->codecpar->format = AV_SAMPLE_FMT_DBL;
|
||||||
break;
|
break;
|
||||||
case media_raw_audio_format::B_AUDIO_INT:
|
case media_raw_audio_format::B_AUDIO_INT:
|
||||||
fStream->codec->sample_fmt = AV_SAMPLE_FMT_S32;
|
fStream->codecpar->format = AV_SAMPLE_FMT_S32;
|
||||||
break;
|
break;
|
||||||
case media_raw_audio_format::B_AUDIO_SHORT:
|
case media_raw_audio_format::B_AUDIO_SHORT:
|
||||||
fStream->codec->sample_fmt = AV_SAMPLE_FMT_S16;
|
fStream->codecpar->format = AV_SAMPLE_FMT_S16;
|
||||||
break;
|
break;
|
||||||
case media_raw_audio_format::B_AUDIO_UCHAR:
|
case media_raw_audio_format::B_AUDIO_UCHAR:
|
||||||
fStream->codec->sample_fmt = AV_SAMPLE_FMT_U8;
|
fStream->codecpar->format = AV_SAMPLE_FMT_U8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case media_raw_audio_format::B_AUDIO_CHAR:
|
case media_raw_audio_format::B_AUDIO_CHAR:
|
||||||
@@ -205,24 +193,24 @@ AVFormatWriter::StreamCookie::Init(media_format* format,
|
|||||||
|
|
||||||
// Now negociate the actual format with the encoder
|
// Now negociate the actual format with the encoder
|
||||||
// First check if the requested format is acceptable
|
// First check if the requested format is acceptable
|
||||||
AVCodec* codec = avcodec_find_encoder(fStream->codec->codec_id);
|
AVCodec* codec = avcodec_find_encoder(fStream->codecpar->codec_id);
|
||||||
|
|
||||||
if (codec == NULL)
|
if (codec == NULL)
|
||||||
return B_MEDIA_BAD_FORMAT;
|
return B_MEDIA_BAD_FORMAT;
|
||||||
|
|
||||||
const enum AVSampleFormat *p = codec->sample_fmts;
|
const enum AVSampleFormat *p = codec->sample_fmts;
|
||||||
for (; *p != -1; p++) {
|
for (; *p != -1; p++) {
|
||||||
if (*p == fStream->codec->sample_fmt)
|
if (*p == fStream->codecpar->format)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// If not, force one of the acceptable ones
|
// If not, force one of the acceptable ones
|
||||||
if (*p == -1) {
|
if (*p == -1) {
|
||||||
fStream->codec->sample_fmt = codec->sample_fmts[0];
|
fStream->codecpar->format = codec->sample_fmts[0];
|
||||||
|
|
||||||
// And finally set the format struct to the accepted format. It is
|
// And finally set the format struct to the accepted format. It is
|
||||||
// then up to the caller to make sure we get data matching that
|
// then up to the caller to make sure we get data matching that
|
||||||
// format.
|
// format.
|
||||||
switch (fStream->codec->sample_fmt) {
|
switch (fStream->codecpar->format) {
|
||||||
case AV_SAMPLE_FMT_FLT:
|
case AV_SAMPLE_FMT_FLT:
|
||||||
format->u.raw_audio.format
|
format->u.raw_audio.format
|
||||||
= media_raw_audio_format::B_AUDIO_FLOAT;
|
= media_raw_audio_format::B_AUDIO_FLOAT;
|
||||||
@@ -254,43 +242,39 @@ AVFormatWriter::StreamCookie::Init(media_format* format,
|
|||||||
switch (format->u.raw_audio.channel_count) {
|
switch (format->u.raw_audio.channel_count) {
|
||||||
default:
|
default:
|
||||||
case 2:
|
case 2:
|
||||||
fStream->codec->channel_layout = AV_CH_LAYOUT_STEREO;
|
fStream->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
fStream->codec->channel_layout = AV_CH_LAYOUT_MONO;
|
fStream->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
fStream->codec->channel_layout = AV_CH_LAYOUT_SURROUND;
|
fStream->codecpar->channel_layout = AV_CH_LAYOUT_SURROUND;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
fStream->codec->channel_layout = AV_CH_LAYOUT_QUAD;
|
fStream->codecpar->channel_layout = AV_CH_LAYOUT_QUAD;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
fStream->codec->channel_layout = AV_CH_LAYOUT_5POINT0;
|
fStream->codecpar->channel_layout = AV_CH_LAYOUT_5POINT0;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
fStream->codec->channel_layout = AV_CH_LAYOUT_5POINT1;
|
fStream->codecpar->channel_layout = AV_CH_LAYOUT_5POINT1;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
fStream->codec->channel_layout = AV_CH_LAYOUT_7POINT1;
|
fStream->codecpar->channel_layout = AV_CH_LAYOUT_7POINT1;
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
fStream->codec->channel_layout = AV_CH_LAYOUT_7POINT1_WIDE;
|
fStream->codecpar->channel_layout = AV_CH_LAYOUT_7POINT1_WIDE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The bits match 1:1 for media_multi_channels and FFmpeg defines.
|
// The bits match 1:1 for media_multi_channels and FFmpeg defines.
|
||||||
fStream->codec->channel_layout = format->u.raw_audio.channel_mask;
|
fStream->codecpar->channel_layout = format->u.raw_audio.channel_mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some formats want stream headers to be separate
|
|
||||||
if ((fContext->oformat->flags & AVFMT_GLOBALHEADER) != 0)
|
|
||||||
fStream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
|
||||||
|
|
||||||
TRACE(" stream->time_base: (%d/%d), codec->time_base: (%d/%d))\n",
|
TRACE(" stream->time_base: (%d/%d), codec->time_base: (%d/%d))\n",
|
||||||
fStream->time_base.num, fStream->time_base.den,
|
fStream->time_base.num, fStream->time_base.den,
|
||||||
fStream->codec->time_base.num, fStream->codec->time_base.den);
|
fStream->codecpar->time_base.num, fStream->codecpar->time_base.den);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Write the AVCodecContext pointer to the user data section of the
|
// Write the AVCodecContext pointer to the user data section of the
|
||||||
@@ -337,7 +321,7 @@ AVFormatWriter::StreamCookie::WriteChunk(const void* chunkBuffer,
|
|||||||
TRACE_PACKET(" PTS: %lld (stream->time_base: (%d/%d), "
|
TRACE_PACKET(" PTS: %lld (stream->time_base: (%d/%d), "
|
||||||
"codec->time_base: (%d/%d))\n", fPacket.pts,
|
"codec->time_base: (%d/%d))\n", fPacket.pts,
|
||||||
fStream->time_base.num, fStream->time_base.den,
|
fStream->time_base.num, fStream->time_base.den,
|
||||||
fStream->codec->time_base.num, fStream->codec->time_base.den);
|
fStream->codecpar->time_base.num, fStream->codecpar->time_base.den);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// TODO: Eventually, we need to write interleaved packets, but
|
// TODO: Eventually, we need to write interleaved packets, but
|
||||||
@@ -395,10 +379,13 @@ AVFormatWriter::~AVFormatWriter()
|
|||||||
#if OPEN_CODEC_CONTEXT
|
#if OPEN_CODEC_CONTEXT
|
||||||
// We only need to close the AVCodecContext when we opened it.
|
// We only need to close the AVCodecContext when we opened it.
|
||||||
// This is experimental, see CommitHeader().
|
// This is experimental, see CommitHeader().
|
||||||
|
|
||||||
|
// NOTE: Since the introduction of AVCodecParameters
|
||||||
|
// I am not sure this logic is correct.
|
||||||
if (fCodecOpened)
|
if (fCodecOpened)
|
||||||
avcodec_close(fContext->streams[i]->codec);
|
avcodec_close(fContext->streams[i]->codec);
|
||||||
#endif
|
#endif
|
||||||
av_freep(&fContext->streams[i]->codec);
|
av_freep(&fContext->streams[i]->codecpar);
|
||||||
av_freep(&fContext->streams[i]);
|
av_freep(&fContext->streams[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009, Stephan Aßmus <[email protected]>
|
* Copyright 2009, Stephan Aßmus <[email protected]>
|
||||||
* Copyright 2014, Colin Günther <[email protected]>
|
* Copyright 2014, Colin Günther <[email protected]>
|
||||||
|
* Copyright 2018, Dario Casalinuovo
|
||||||
* All rights reserved. Distributed under the terms of the GNU L-GPL license.
|
* All rights reserved. Distributed under the terms of the GNU L-GPL license.
|
||||||
*/
|
*/
|
||||||
#ifndef UTILITIES_H
|
#ifndef UTILITIES_H
|
||||||
@@ -75,6 +76,42 @@ ConvertAVCodecContextToVideoAspectWidthAndHeight(AVCodecContext& contextIn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void
|
||||||
|
ConvertAVCodecParametersToVideoAspectWidthAndHeight(AVCodecParameters& parametersIn,
|
||||||
|
uint16& pixelWidthAspectOut, uint16& pixelHeightAspectOut)
|
||||||
|
{
|
||||||
|
assert(parametersIn.sample_aspect_ratio.num >= 0);
|
||||||
|
assert(parametersIn.width > 0);
|
||||||
|
assert(parametersIn.height > 0);
|
||||||
|
|
||||||
|
// The following code is based on code originally located in
|
||||||
|
// AVFormatReader::Stream::Init() and thus should be copyrighted to Stephan
|
||||||
|
// Aßmus
|
||||||
|
AVRational pixelAspectRatio;
|
||||||
|
|
||||||
|
if (parametersIn.sample_aspect_ratio.num == 0
|
||||||
|
|| parametersIn.sample_aspect_ratio.den == 0) {
|
||||||
|
// AVCodecContext doesn't contain a video aspect ratio, so calculate it
|
||||||
|
// ourselve based solely on the video dimensions
|
||||||
|
av_reduce(&pixelAspectRatio.num, &pixelAspectRatio.den, parametersIn.width,
|
||||||
|
parametersIn.height, 1024 * 1024);
|
||||||
|
|
||||||
|
pixelWidthAspectOut = static_cast<int16>(pixelAspectRatio.num);
|
||||||
|
pixelHeightAspectOut = static_cast<int16>(pixelAspectRatio.den);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AVCodecContext contains a video aspect ratio, so use it
|
||||||
|
av_reduce(&pixelAspectRatio.num, &pixelAspectRatio.den,
|
||||||
|
parametersIn.width * parametersIn.sample_aspect_ratio.num,
|
||||||
|
parametersIn.height * parametersIn.sample_aspect_ratio.den,
|
||||||
|
1024 * 1024);
|
||||||
|
|
||||||
|
pixelWidthAspectOut = static_cast<int16>(pixelAspectRatio.num);
|
||||||
|
pixelHeightAspectOut = static_cast<int16>(pixelAspectRatio.den);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! \brief Converts the Media Kits notation of video aspect ratio into FFmpegs
|
/*! \brief Converts the Media Kits notation of video aspect ratio into FFmpegs
|
||||||
notation.
|
notation.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user