Skip to content

Instantly share code, notes, and snippets.

@Neko3000
Last active September 28, 2020 06:55
Show Gist options
  • Save Neko3000/1a2b80967217d8831dd0cd42f1b33dc0 to your computer and use it in GitHub Desktop.
Save Neko3000/1a2b80967217d8831dd0cd42f1b33dc0 to your computer and use it in GitHub Desktop.
typedef struct AVCodecParameters {
/**
* General type of the encoded data.
*/
enum AVMediaType codec_type;
/**
* Specific type of the encoded data (the codec used).
*/
enum AVCodecID codec_id;
/**
* Additional information about the codec (corresponds to the AVI FOURCC).
*/
uint32_t codec_tag;
/**
* Extra binary data needed for initializing the decoder, codec-dependent.
*
* Must be allocated with av_malloc() and will be freed by
* avcodec_parameters_free(). The allocated size of extradata must be at
* least extradata_size + AV_INPUT_BUFFER_PADDING_SIZE, with the padding
* bytes zeroed.
*/
uint8_t *extradata;
/**
* Size of the extradata content in bytes.
*/
int extradata_size;
/**
* - video: the pixel format, the value corresponds to enum AVPixelFormat.
* - audio: the sample format, the value corresponds to enum AVSampleFormat.
*/
int format;
/**
* The average bitrate of the encoded data (in bits per second).
*/
int64_t bit_rate;
/**
* The number of bits per sample in the codedwords.
*
* This is basically the bitrate per sample. It is mandatory for a bunch of
* formats to actually decode them. It's the number of bits for one sample in
* the actual coded bitstream.
*
* This could be for example 4 for ADPCM
* For PCM formats this matches bits_per_raw_sample
* Can be 0
*/
int bits_per_coded_sample;
/**
* This is the number of valid bits in each output sample. If the
* sample format has more bits, the least significant bits are additional
* padding bits, which are always 0. Use right shifts to reduce the sample
* to its actual size. For example, audio formats with 24 bit samples will
* have bits_per_raw_sample set to 24, and format set to AV_SAMPLE_FMT_S32.
* To get the original sample use "(int32_t)sample >> 8"."
*
* For ADPCM this might be 12 or 16 or similar
* Can be 0
*/
int bits_per_raw_sample;
/**
* Codec-specific bitstream restrictions that the stream conforms to.
*/
int profile;
int level;
/**
* Video only. The dimensions of the video frame in pixels.
*/
int width;
int height;
...
} AVCodecParameters;
//
// AVStreamTestUnit.m
// SimplePlayer
//
// Created by Xueliang Chen on 2020/9/22.
// Copyright © 2020 Xueliang Chen. All rights reserved.
//
#import "AVStreamTestUnit.h"
#import <mobileffmpeg/ffmpeg.h>
#import <libavutil/pixdesc.h>
@implementation AVStreamTestUnit
- (void)initAVFormatContext{
av_register_all();
NSString* contentPath = [[NSBundle mainBundle] pathForResource:@"sm25392237" ofType:@".mp4"];
const char* clangContentPath = [contentPath cStringUsingEncoding:kCFStringEncodingUTF8];
AVFormatContext* formatCtx = NULL;
if(0 != avformat_open_input(&formatCtx, clangContentPath, NULL, NULL)){
avformat_close_input(&formatCtx);
NSLog(@"open file failed.");
return;
}
formatCtx->probesize = 512 * 1024;
formatCtx->max_analyze_duration = 5 * AV_TIME_BASE;
int streamCount = formatCtx->nb_streams;
for(int i = 0; i < streamCount; i++){
AVStream* stream = formatCtx->streams[i];
AVCodecContext* codecCtx = avcodec_alloc_context3(NULL);
if(!codecCtx){
NSLog(@"alloc AVCodecContext failed.");
return;
}
NSInteger ret = avcodec_parameters_to_context(codecCtx, stream->codecpar);
if(ret < 0){
NSLog(@"AVCodec paramters to context failed.");
avcodec_free_context(&codecCtx);
return;
}
av_codec_set_pkt_timebase(codecCtx, stream->time_base);
enum AVMediaType mediaType = codecCtx->codec_type;
switch (mediaType) {
case AVMEDIA_TYPE_AUDIO:{
int channelCount = codecCtx->channels;
int duaration = stream->duration * av_q2d(stream->time_base);
int sampleRate = codecCtx->sample_rate;
int64_t bitRate = codecCtx->bit_rate;
enum AVCodecID codecID = codecCtx->codec_id;
const char* codecDesc = avcodec_get_name(codecID);
enum AVSampleFormat sampleFormat = codecCtx->sample_fmt;
const char* sampleFormatDesc = av_get_sample_fmt_name(sampleFormat);
NSLog(@"%@", [NSString stringWithFormat:@"%d - 读取到音频流,声道数 = %d,时长 = %d s,采样率 = %.1f,比特率 = %d Kbps,编码格式 = %s,采样格式 = %s.",i, channelCount, duaration, sampleRate / 1000.0, (int)(bitRate / 1000.0), codecDesc, sampleFormatDesc]);
}
break;
case AVMEDIA_TYPE_VIDEO:{
int width = codecCtx->width;
int height = codecCtx->height;
int duration = stream->duration * av_q2d(stream->time_base);
int64_t bitRate = codecCtx->bit_rate;
enum AVCodecID codecID = codecCtx->codec_id;
const char* codecDesc = avcodec_get_name(codecID);
enum AVPixelFormat pixelFormat = codecCtx->pix_fmt;
const char* pixelFormatDesc = av_get_pix_fmt_name(pixelFormat);
double fps = 0.04;
if(stream->avg_frame_rate.den && stream->avg_frame_rate.num){
fps = av_q2d(stream->avg_frame_rate);
}
else if(stream->r_frame_rate.den && stream->r_frame_rate.num){
fps = av_q2d(stream->r_frame_rate);
}
else if(stream->time_base.den && stream->time_base.num){
fps = 1.0 / av_q2d(stream->time_base);
}
NSLog(@"%@", [NSString stringWithFormat:@"%d - 读取到视频流,帧宽度 = %d,帧高度 = %d,时长 = %d,比特率 = %d,编码格式 = %s,像素格式 = %s,fps = %.3f fps.",i,width,height,duration,(int)(bitRate / 1000.0), codecDesc, pixelFormatDesc,fps]);
}
break;
case AVMEDIA_TYPE_ATTACHMENT:{
NSLog(@"%d - 读取到附加信息流.",i);
}
break;
default:{
NSLog(@"%d - 读取到其他信息流.",i);
}
break;
}
avcodec_free_context(&codecCtx);
}
avformat_close_input(&formatCtx);
}
- (void)run{
[self initAVFormatContext];
}
@end
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
{
int i, count = 0, ret = 0, j;
int64_t read_size;
AVStream *st;
AVCodecContext *avctx;
AVPacket pkt1;
int64_t old_offset = avio_tell(ic->pb);
// new streams might appear, no options for those
int orig_nb_streams = ic->nb_streams;
int flush_codecs;
int64_t max_analyze_duration = ic->max_analyze_duration;
int64_t max_stream_analyze_duration;
int64_t max_subtitle_analyze_duration;
int64_t probesize = ic->probesize;
int eof_reached = 0;
int *missing_streams = av_opt_ptr(ic->iformat->priv_class, ic->priv_data, "missing_streams");
flush_codecs = probesize > 0;
av_opt_set(ic, "skip_clear", "1", AV_OPT_SEARCH_CHILDREN);
max_stream_analyze_duration = max_analyze_duration;
max_subtitle_analyze_duration = max_analyze_duration;
if (!max_analyze_duration) {
max_stream_analyze_duration =
max_analyze_duration = 5*AV_TIME_BASE;
max_subtitle_analyze_duration = 30*AV_TIME_BASE;
if (!strcmp(ic->iformat->name, "flv"))
max_stream_analyze_duration = 90*AV_TIME_BASE;
if (!strcmp(ic->iformat->name, "mpeg") || !strcmp(ic->iformat->name, "mpegts"))
max_stream_analyze_duration = 7*AV_TIME_BASE;
}
if (ic->pb)
av_log(ic, AV_LOG_DEBUG, "Before avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d nb_streams:%d\n",
avio_tell(ic->pb), ic->pb->bytes_read, ic->pb->seek_count, ic->nb_streams);
...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment