【FFLAY】 struct Frame 和 FrameQueue队列

1 Frame

typedef struct Frame {
    AVFrame *frame;    // 指向数据帧
    AVSubtitle sub;    // ⽤于字幕
    int serial;        // 播放序列,在seek的操作时serial会变化
    double pts;        // 时间戳,单位为秒
    double duration;   // 该帧持续时间,单位为秒
    int64_t pos;       // 该帧在输⼊⽂件中的字节位置
    int width;         // 图像宽度
    int height;        // 图像⾼读
    int format; 
    // 对于图像为(enum AVPixelFormat), 
    // 对于声⾳则为(enum AVSampleFormat)     
    AVRational sar; // 图像的宽⾼⽐,如果未知或未指定则为0/1
    int uploaded; // ⽤来记录该帧是否已经显示过?
    int flip_v; // =1则旋转180, = 0则正常播放
} Frame;

真正存储解码后⾳视频数据的结构体为AVFrame ,存储字幕则使⽤AVSubtitle,该Frame的设计是为了⾳频、视频、字幕帧通⽤,所以Frame结构体的设计类似AVFrame,部分成员变量只对不同类型有作⽤,⽐如sar只对视频有作⽤。
⾥⾯也包含了serial播放序列(每次seek时都切换serial),sar(图像的宽⾼⽐(16:9,4:3…),该值来⾃AVFrame结构体的sample_aspect_ratio变量)。

问题
1 这个 int64_t pos 这个·怎么表示的?时间or帧排序?

2 FrameQueue

typedef struct FrameQueue {
    Frame queue[FRAME_QUEUE_SIZE];
    //FRAME_QUEUE_SIZE 最⼤size, 数字太⼤时会占⽤⼤量的内存,需要注意该值的设置
    int rindex;// 读索引。待播放时读取此帧进⾏播放,播放后此帧成为上⼀帧
    int windex; // 写索引
    int size; // 当前总帧数
    int max_size; // 可存储最⼤帧数
    int keep_last; // = 1说明要在队列⾥⾯保持最后⼀帧的数据不释放,只在销毁队列的时候才将其真正释放
    int rindex_shown; // 初始化为0,配合keep_last=1使⽤
    SDL_mutex *mutex;  // 互斥量
    SDL_cond *cond;    // 条件变量
    PacketQueue *pktq;  // 数据包缓冲队列
} FrameQueue;

1 FrameQueue是⼀个环形缓冲区(ring buffer),是⽤数组实现的⼀个FIFO。数组⽅式的环形缓冲区适合于事先明确了缓冲区的最⼤容量的情形。
2 ffplay中创建了三个frame_queue:⾳频frame_queue,视频frame_queue,字幕frame_queue。每⼀个frame_queue⼀个写端⼀个读端,写端位于解码线程,读端位于播放线程。

问题
1 Frame queue[FRAME_QUEUE_SIZE] 与 max_size 关系?

三 读写frame队列

1 写 frame 队列

static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double duration, int64_t pos, int serial)
{
    Frame *vp;

#if defined(DEBUG_SYNC)
    printf("frame_type=%c pts=%0.3f\n",
           av_get_picture_type_char(src_frame->pict_type), pts);
#endif

    if (!(vp = frame_queue_peek_writable(&is->pictq)))
        return -1;

    vp->sar = src_frame->sample_aspect_ratio;
    vp->uploaded = 0;

    vp->width = src_frame->width;
    vp->height = src_frame->height;
    vp->format = src_frame->format;

    vp->pts = pts;
    vp->duration = duration;
    vp->pos = pos;
    vp->serial = serial;

    set_default_window_size(vp->width, vp->height, vp->sar);

    av_frame_move_ref(vp->frame, src_frame);
    frame_queue_push(&is->pictq);
    return 0;
}

A frame_queue_peek_writable //获取队列里面成员
B 对队列成员 进行赋值
C frame_queue_push//更新状态

你可能感兴趣的:(媒体)