前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >音视频面试题集锦(第 13 期)

音视频面试题集锦(第 13 期)

作者头像
关键帧
发布2024-01-05 12:45:34
2620
发布2024-01-05 12:45:34
举报
文章被收录于专栏:关键帧Keyframe

下面是第 13 期面试题精选:

  • 1、AVPlayer 中如何实现视频片段加速预览播放?
  • 2、如何高效获取一个视频的关键帧序列?
  • 3、SPS 和 PPS 在 extradata 中的作用是什么?
  • 4、I 帧和 IDR 帧有什么区别?在什么情况下 I 帧不是 IDR 帧?

1、AVPlayer 中如何实现视频片段加速预览播放?

在编辑场景用 AVPlayer 来实现预览播放器时,对视频中某一段内容进行加速播放的实现代码如下:

代码语言:javascript
复制

// 创建 AVMutableComposition 对象
AVMutableComposition *composition = [AVMutableComposition composition];
// 将视频文件加载到 AVURLAsset 对象中
NSURL *videoURL = [[NSBundle mainBundle] URLForResource:@"your_video" withExtension:@"mp4"];
AVURLAsset *videoAsset = [AVURLAsset URLAssetWithURL:videoURL options:nil];
// 将视频的前 3 秒进行加速处理
CMTime startTime = kCMTimeZero;
CMTime duration = CMTimeMake(3, 1); // 加速的时间范围为前 3 秒
CMTimeRange timeRange = CMTimeRangeMake(startTime, duration);
[composition scaleTimeRange:timeRange toDuration:CMTimeMake(1, 1)]; 
// 将时间范围加速到 1 秒
// 创建 AVPlayerItem 对象并将组合后的视频添加到其中
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:composition];
// 创建 AVPlayer 对象并将 AVPlayerItem 对象添加到其中
AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];

2、如何高效获取一个视频的关键帧序列?

获取一个视频的关键帧序列,基于 Android 平台 API 实现:

代码语言:javascript
复制
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(getVideoPath());

int trackIndex = MediaExtractorUtil.selectVideoTrack(extractor);
extractor.selectTrack(trackIndex);

List<Long> keyframeTimestampsMS = new ArrayList<Long>();

while (extractor.getSampleTime() != -1) {
    long sampleTime = extractor.getSampleTime();

    if ((extractor.getSampleFlags() & MediaExtractor.SAMPLE_FLAG_SYNC) > 0) {
        keyframeTimestampsMS.add(sampleTime / 1000);
    }
    // 此处表示 extractor seek 的间隔为 1000 微妙
    extractor.seekTo(sampleTime + 1000, MediaExtractor.SEEK_TO_NEXT_SYNC);
}

获取一个视频的关键帧序列,基于 FFmpeg 实现:

代码语言:javascript
复制
#include "libavcodec/avcodec.h"  
#include "libavutil/ff_time.h"  
#include "libavformat/avformat.h"  
#include "libavformat/avc.h"

AVFormatContext* formatCtx = avformat_alloc_context();  
avformat_open_input(&formatCtx, path.c_str(), NULL, NULL);  
int videoIndex = -1;  
  
for (int i = 0; i < formatCtx->nb_streams; i++) {  
    AVStream* stream = formatCtx->streams[i];  
    AVMediaType type = stream->codecpar->codec_type;  
    if (type == AVMEDIA_TYPE_VIDEO) {  
        videoIndex = i;  
        break;  
    }
}  
if (videoIndex > 0) {
    AVStream* videoStream = formatCtx->streams[videoIndex];  
    AVInputFormat* iformat = formatCtx->iformat;  
    if (strcmp(iformat->name, "mov,mp4,m4a,3gp,3g2,mj2") == 0) {  
        std::vector<int64_t> keyframe_time_list_tmp;  
        MOVStreamContext* sc = (MOVStreamContext*) videoStream->priv_data;  
        for (int videoIndex = 0; videoIndex < videoStream->nb_index_entries; videoIndex++) {  
            AVIndexEntry indexEntry = videoStream->index_entries[videoIndex];  
            if (indexEntry.flags & AVINDEX_KEYFRAME) {  
                MOVStts cttsData = {0};  
                if (sc && sc->ctts_count == videoStream->nb_index_entries) {  
                    cttsData = sc->ctts_data[videoIndex];  
                } 
                double doublePts = (indexEntry.timestamp + sc->dts_shift + cttsData.duration) * av_q2d(videoStream->time_base) * 1000.0;  
                int64_t ptsTime = ceil(doublePts);  
                keyframe_time_list_tmp.push_back(ptsTime);  
            }    
        }  
    }
}

3、SPS 和 PPS 在 extradata 中的作用是什么?

SPS(Sequence Parameter Set)和 PPS(Picture Parameter Set)是 H.264 视频编码中的两种重要参数集。它们包含了视频序列的特性和参数信息,对于解码器来说非常重要。

SPS 包含了视频序列的全局参数,如分辨率、帧率、颜色空间等。PPS 则包含了与特定图像相关的参数,如切片组的配置、参考帧的使用等。

在 extradata 中,SPS 和 PPS 的作用是为解码器提供视频序列的配置信息,以确保解码器能够正确地解释和处理视频数据。通过提供这些参数集,解码器能够准确地还原视频序列的特性,从而实现高质量的视频解码。

4、I 帧和 IDR 帧有什么区别?在什么情况下 I 帧不是 IDR 帧?

I 帧:I 帧是视频序列中的关键帧,它是一个完整的图像帧,类似于 JPEG 或 BMP 图像文件。I 帧不依赖于其他帧,因此可以独立解码和显示。在视频序列中,I 帧通常用于随机访问点,也作为其他帧解码的参考。

IDR 帧:IDR 帧是一种特殊的 I 帧,它具有刷新解码器缓冲区的功能。当解码器接收到 IDR 帧时,它会清除之前的解码状态,确保从该帧开始解码,从而避免错误传播。IDR 帧通常用于视频序列的随机访问点,以及在视频传输或存储中用于错误恢复。

因此 IDR 帧一定是 I 帧,但是 I 帧则不一定是 IDR 帧。在遇到 OpenGOP 的情况下,就会出现 I 帧为非 IDR 帧的情况。

OpenGOP

如上图所示右数第一个 I 帧就是一个非 IDR 的 I 帧,前一个 GOP 中的 B 帧依赖了当前 GOP 的 I 帧。所以右数第一个 I 帧接受时,不能刷新解码器,否则上一个 GOP 中的 B 帧无法被成功解码,可能会出现花屏或者报错。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-12-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 关键帧Keyframe 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、AVPlayer 中如何实现视频片段加速预览播放?
  • 2、如何高效获取一个视频的关键帧序列?
  • 3、SPS 和 PPS 在 extradata 中的作用是什么?
  • 4、I 帧和 IDR 帧有什么区别?在什么情况下 I 帧不是 IDR 帧?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档