首页 > 代码库 > [原]零基础学习视频解码之解码声音

[原]零基础学习视频解码之解码声音

  关于视频解码以及使用SDL显示详情见:[原]零基础学习视频解码之解码图像 

  SDL播放声音的方式是这样的:

  你建立你的音频选项:采样率(在SDL中称为"频率"),通道数,等等,我们还应该设置一个回调函数和用户数据。当我们开始播放音频,SDL会不断的回调这个函数,让它充满一定数量字节的音频缓冲区,然后我们把这些信息放到SDL_AudioSpec数据结构中,我们接着调用SDL_OpenAudio,这将打开音频设备,还给我们一个AudioSpec结构。

  freq:采样率

  format:我们将给SDL什么样的格式

  channels:音频通道

  silence:音频缓冲区默认值,通常为0

  samples:当SDL向我们请求更多的音频缓冲区的大小的时候设置的

  callback:回调函数

  userdata:SDL会给我们的回调void指针的用户数据,我们必须让它知道我们的编解码器上下文

  现在我们开始获取流音频信息,但我们怎么处理这些信息?解决的办法是要创造一种数据结构,我们可以在audio_callback得到音频数据然后保存获取到的数据包!所以我们要做的是创建一个队列的数据包。ffmpeg甚至还带有一个结构来帮助我们做这:AVPacketList,这仅仅是一个链表的数据包,我们还需要自己维护接受到的数据包队列。

  首先还是配置Eclipse相关依赖库的环境:

  Project->Properties->C/C++ General->Path and Symbols->Libraries->Add->SDL、avcode、avutil、avformat、swscale

  一、定义一个数据结构用来保存AVPacketList队列

/* ============================================================================ Name        : VideoDecodeTutorial2_1.c Author      : clarck Version     : Copyright   : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include "SDL/SDL.h"#include "SDL/SDL_thread.h"#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavutil/pixfmt.h"#include "libswscale/swscale.h"#ifdef __MINGW32__#undef main /* Prevents SDL from overriding main() */#endif#define SDL_AUDIO_BUFFER_SIZE 1024#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audiotypedef struct PacketQueue {    AVPacketList *first_pkt, *last_pkt;    int nb_packets;    int size;    SDL_mutex *mutex;    SDL_cond *cond;} PacketQueue;PacketQueue audioq;int main(int argc, char* args[]) {    return EXIT_SUCCESS;}

  二、初始化这个数据队列:

/* ============================================================================ Name        : VideoDecodeTutorial2_1.c Author      : clarck Version     : Copyright   : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include "SDL/SDL.h"#include "SDL/SDL_thread.h"#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavutil/pixfmt.h"#include "libswscale/swscale.h"#ifdef __MINGW32__#undef main /* Prevents SDL from overriding main() */#endif#define SDL_AUDIO_BUFFER_SIZE 1024#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audiotypedef struct PacketQueue {    AVPacketList *first_pkt, *last_pkt;    int nb_packets;    int size;    SDL_mutex *mutex;    SDL_cond *cond;} PacketQueue;PacketQueue audioq;int quit = 0;void packet_queue_init(PacketQueue *q) {    memset(q, 0, sizeof(PacketQueue));    q->mutex = SDL_CreateMutex();    q->cond = SDL_CreateCond();}int main(int argc, char* args[]) {    return EXIT_SUCCESS;}

  你会注意到,我们有一个互斥体和条件变量。这是因为SDL用一个单独的线程运行音频处理。如果我们不把排好队,我们真的会毁了我们的数据。接下来我们将看到如何在队列的实现。

  三、添加一个AVPacket到队列中

/* ============================================================================ Name        : VideoDecodeTutorial2_1.c Author      : clarck Version     : Copyright   : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include "SDL/SDL.h"#include "SDL/SDL_thread.h"#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavutil/pixfmt.h"#include "libswscale/swscale.h"#ifdef __MINGW32__#undef main /* Prevents SDL from overriding main() */#endif#define SDL_AUDIO_BUFFER_SIZE 1024#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audiotypedef struct PacketQueue {    AVPacketList *first_pkt, *last_pkt;    int nb_packets;    int size;    SDL_mutex *mutex;    SDL_cond *cond;} PacketQueue;PacketQueue audioq;int quit = 0;void packet_queue_init(PacketQueue *q) {    memset(q, 0, sizeof(PacketQueue));    q->mutex = SDL_CreateMutex();    q->cond = SDL_CreateCond();}int packet_queue_put(PacketQueue *q, AVPacket *pkt) {    AVPacketList *pkt1;    if (av_dup_packet(pkt) < 0) {        return -1;    }    pkt1 = av_malloc(sizeof(AVPacketList));    if (!pkt1)        return -1;    pkt1->pkt = *pkt;    pkt1->next = NULL;    SDL_LockMutex(q->mutex);    if (!q->last_pkt)        q->first_pkt = pkt1;    else        q->last_pkt->next = pkt1;    q->last_pkt = pkt1;    q->nb_packets++;    q->size += pkt1->pkt.size;    SDL_CondSignal(q->cond);    SDL_UnlockMutex(q->mutex);    return 0;}int main(int argc, char* args[]) {    return EXIT_SUCCESS;}

  四、从队列中获取一个AVPacket

/* ============================================================================ Name        : VideoDecodeTutorial2_1.c Author      : clarck Version     : Copyright   : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include "SDL/SDL.h"#include "SDL/SDL_thread.h"#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavutil/pixfmt.h"#include "libswscale/swscale.h"#ifdef __MINGW32__#undef main /* Prevents SDL from overriding main() */#endif#define SDL_AUDIO_BUFFER_SIZE 1024#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audiotypedef struct PacketQueue {    AVPacketList *first_pkt, *last_pkt;    int nb_packets;    int size;    SDL_mutex *mutex;    SDL_cond *cond;} PacketQueue;PacketQueue audioq;int quit = 0;void packet_queue_init(PacketQueue *q) {    memset(q, 0, sizeof(PacketQueue));    q->mutex = SDL_CreateMutex();    q->cond = SDL_CreateCond();}int packet_queue_put(PacketQueue *q, AVPacket *pkt) {    AVPacketList *pkt1;    if (av_dup_packet(pkt) < 0) {        return -1;    }    pkt1 = av_malloc(sizeof(AVPacketList));    if (!pkt1)        return -1;    pkt1->pkt = *pkt;    pkt1->next = NULL;    SDL_LockMutex(q->mutex);    if (!q->last_pkt)        q->first_pkt = pkt1;    else        q->last_pkt->next = pkt1;    q->last_pkt = pkt1;    q->nb_packets++;    q->size += pkt1->pkt.size;    SDL_CondSignal(q->cond);    SDL_UnlockMutex(q->mutex);    return 0;}static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) {    AVPacketList *pkt1;    int ret;    SDL_LockMutex(q->mutex);    for (;;) {        if (quit) {            ret = -1;            break;        }        pkt1 = q->first_pkt;        if (pkt1) {            q->first_pkt = pkt1->next;            if (!q->first_pkt)                q->last_pkt = NULL;            q->nb_packets--;            q->size -= pkt1->pkt.size;            *pkt = pkt1->pkt;            av_free(pkt1);            ret = 1;            break;        } else if (!block) {            ret = 0;            break;        } else {            SDL_CondWait(q->cond, q->mutex);        }    }    SDL_UnlockMutex(q->mutex);    return ret;}int main(int argc, char* args[]) {    return EXIT_SUCCESS;}

  五、解码音频

/* ============================================================================ Name        : VideoDecodeTutorial2_1.c Author      : clarck Version     : Copyright   : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include "SDL/SDL.h"#include "SDL/SDL_thread.h"#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavutil/pixfmt.h"#include "libswscale/swscale.h"#ifdef __MINGW32__#undef main /* Prevents SDL from overriding main() */#endif#define SDL_AUDIO_BUFFER_SIZE 1024#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audiotypedef struct PacketQueue {    AVPacketList *first_pkt, *last_pkt;    int nb_packets;    int size;    SDL_mutex *mutex;    SDL_cond *cond;} PacketQueue;PacketQueue audioq;int quit = 0;void packet_queue_init(PacketQueue *q) {    memset(q, 0, sizeof(PacketQueue));    q->mutex = SDL_CreateMutex();    q->cond = SDL_CreateCond();}int packet_queue_put(PacketQueue *q, AVPacket *pkt) {    AVPacketList *pkt1;    if (av_dup_packet(pkt) < 0) {        return -1;    }    pkt1 = av_malloc(sizeof(AVPacketList));    if (!pkt1)        return -1;    pkt1->pkt = *pkt;    pkt1->next = NULL;    SDL_LockMutex(q->mutex);    if (!q->last_pkt)        q->first_pkt = pkt1;    else        q->last_pkt->next = pkt1;    q->last_pkt = pkt1;    q->nb_packets++;    q->size += pkt1->pkt.size;    SDL_CondSignal(q->cond);    SDL_UnlockMutex(q->mutex);    return 0;}static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) {    AVPacketList *pkt1;    int ret;    SDL_LockMutex(q->mutex);    for (;;) {        if (quit) {            ret = -1;            break;        }        pkt1 = q->first_pkt;        if (pkt1) {            q->first_pkt = pkt1->next;            if (!q->first_pkt)                q->last_pkt = NULL;            q->nb_packets--;            q->size -= pkt1->pkt.size;            *pkt = pkt1->pkt;            av_free(pkt1);            ret = 1;            break;        } else if (!block) {            ret = 0;            break;        } else {            SDL_CondWait(q->cond, q->mutex);        }    }    SDL_UnlockMutex(q->mutex);    return ret;}int audio_decode_frame(AVCodecContext *aCodecCtx, uint8_t *audio_buf,        int buf_size) {    static AVPacket pkt;    static uint8_t *audio_pkt_data =http://www.mamicode.com/ NULL;    static int audio_pkt_size = 0;    static AVFrame frame;    int len1, data_size = 0;    for (;;) {        while (audio_pkt_size > 0) {            int got_frame = 0;            len1 = avcodec_decode_audio4(aCodecCtx, &frame, &got_frame, &pkt);            if (len1 < 0) {                /* if error, skip frame */                audio_pkt_size = 0;                break;            }            audio_pkt_data += len1;            audio_pkt_size -= len1;            if (got_frame) {                data_size = frame.linesize[0];                /*                 data_size = av_samples_get_buffer_size(NULL,                 aCodecCtx->channels, frame.nb_samples,                 aCodecCtx->sample_fmt, 1);                 */                memcpy(audio_buf, frame.data[0], data_size);            }            if (data_size <= 0) {                /* No data yet, get more frames */                continue;            }            /* We have data, return it and come back for more later */            return data_size;        }        if (pkt.data)            av_free_packet(&pkt);        if (quit) {            return -1;        }        if (packet_queue_get(&audioq, &pkt, 1) < 0) {            return -1;        }        audio_pkt_data = pkt.data;        audio_pkt_size = pkt.size;    }    return 0;}int main(int argc, char* args[]) {    return EXIT_SUCCESS;}

  六、处理call_back

/* ============================================================================ Name        : VideoDecodeTutorial2_1.c Author      : clarck Version     : Copyright   : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include "SDL/SDL.h"#include "SDL/SDL_thread.h"#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavutil/pixfmt.h"#include "libswscale/swscale.h"#ifdef __MINGW32__#undef main /* Prevents SDL from overriding main() */#endif#define SDL_AUDIO_BUFFER_SIZE 1024#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audiotypedef struct PacketQueue {    AVPacketList *first_pkt, *last_pkt;    int nb_packets;    int size;    SDL_mutex *mutex;    SDL_cond *cond;} PacketQueue;PacketQueue audioq;int quit = 0;void packet_queue_init(PacketQueue *q) {    memset(q, 0, sizeof(PacketQueue));    q->mutex = SDL_CreateMutex();    q->cond = SDL_CreateCond();}int packet_queue_put(PacketQueue *q, AVPacket *pkt) {    AVPacketList *pkt1;    if (av_dup_packet(pkt) < 0) {        return -1;    }    pkt1 = av_malloc(sizeof(AVPacketList));    if (!pkt1)        return -1;    pkt1->pkt = *pkt;    pkt1->next = NULL;    SDL_LockMutex(q->mutex);    if (!q->last_pkt)        q->first_pkt = pkt1;    else        q->last_pkt->next = pkt1;    q->last_pkt = pkt1;    q->nb_packets++;    q->size += pkt1->pkt.size;    SDL_CondSignal(q->cond);    SDL_UnlockMutex(q->mutex);    return 0;}static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) {    AVPacketList *pkt1;    int ret;    SDL_LockMutex(q->mutex);    for (;;) {        if (quit) {            ret = -1;            break;        }        pkt1 = q->first_pkt;        if (pkt1) {            q->first_pkt = pkt1->next;            if (!q->first_pkt)                q->last_pkt = NULL;            q->nb_packets--;            q->size -= pkt1->pkt.size;            *pkt = pkt1->pkt;            av_free(pkt1);            ret = 1;            break;        } else if (!block) {            ret = 0;            break;        } else {            SDL_CondWait(q->cond, q->mutex);        }    }    SDL_UnlockMutex(q->mutex);    return ret;}int audio_decode_frame(AVCodecContext *aCodecCtx, uint8_t *audio_buf,        int buf_size) {    static AVPacket pkt;    static uint8_t *audio_pkt_data =http://www.mamicode.com/ NULL;    static int audio_pkt_size = 0;    static AVFrame frame;    int len1, data_size = 0;    for (;;) {        while (audio_pkt_size > 0) {            int got_frame = 0;            len1 = avcodec_decode_audio4(aCodecCtx, &frame, &got_frame, &pkt);            if (len1 < 0) {                /* if error, skip frame */                audio_pkt_size = 0;                break;            }            audio_pkt_data += len1;            audio_pkt_size -= len1;            if (got_frame) {                data_size = frame.linesize[0];                /*                 data_size = av_samples_get_buffer_size(NULL,                 aCodecCtx->channels, frame.nb_samples,                 aCodecCtx->sample_fmt, 1);                 */                memcpy(audio_buf, frame.data[0], data_size);            }            if (data_size <= 0) {                /* No data yet, get more frames */                continue;            }            /* We have data, return it and come back for more later */            return data_size;        }        if (pkt.data)            av_free_packet(&pkt);        if (quit) {            return -1;        }        if (packet_queue_get(&audioq, &pkt, 1) < 0) {            return -1;        }        audio_pkt_data = pkt.data;        audio_pkt_size = pkt.size;    }    return 0;}void audio_callback(void *userdata, Uint8 *stream, int len) {    AVCodecContext *aCodecCtx = (AVCodecContext *) userdata;    int len1, audio_size;    static uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];    static unsigned int audio_buf_size = 0;    static unsigned int audio_buf_index = 0;    while (len > 0) {        if (audio_buf_index >= audio_buf_size) {            /* We have already sent all our data; get more */            audio_size = audio_decode_frame(aCodecCtx, audio_buf,                    sizeof(audio_buf));            if (audio_size < 0) {                /* If error, output silence */                audio_buf_size = 1024; // arbitrary?                memset(audio_buf, 0, audio_buf_size);            } else {                audio_buf_size = audio_size;            }            audio_buf_index = 0;        }        len1 = audio_buf_size - audio_buf_index;        if (len1 > len)            len1 = len;        memcpy(stream, (uint8_t *) audio_buf + audio_buf_index, len1);        len -= len1;        stream += len1;        audio_buf_index += len1;    }}int main(int argc, char* args[]) {    return EXIT_SUCCESS;}

  七、初始化音频相关的变量

/* ============================================================================ Name        : VideoDecodeTutorial2_1.c Author      : clarck Version     : Copyright   : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include "SDL/SDL.h"#include "SDL/SDL_thread.h"#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavutil/pixfmt.h"#include "libswscale/swscale.h"#ifdef __MINGW32__#undef main /* Prevents SDL from overriding main() */#endif#define SDL_AUDIO_BUFFER_SIZE 1024#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audiotypedef struct PacketQueue {    AVPacketList *first_pkt, *last_pkt;    int nb_packets;    int size;    SDL_mutex *mutex;    SDL_cond *cond;} PacketQueue;PacketQueue audioq;int quit = 0;void packet_queue_init(PacketQueue *q) {    memset(q, 0, sizeof(PacketQueue));    q->mutex = SDL_CreateMutex();    q->cond = SDL_CreateCond();}int packet_queue_put(PacketQueue *q, AVPacket *pkt) {    AVPacketList *pkt1;    if (av_dup_packet(pkt) < 0) {        return -1;    }    pkt1 = av_malloc(sizeof(AVPacketList));    if (!pkt1)        return -1;    pkt1->pkt = *pkt;    pkt1->next = NULL;    SDL_LockMutex(q->mutex);    if (!q->last_pkt)        q->first_pkt = pkt1;    else        q->last_pkt->next = pkt1;    q->last_pkt = pkt1;    q->nb_packets++;    q->size += pkt1->pkt.size;    SDL_CondSignal(q->cond);    SDL_UnlockMutex(q->mutex);    return 0;}static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) {    AVPacketList *pkt1;    int ret;    SDL_LockMutex(q->mutex);    for (;;) {        if (quit) {            ret = -1;            break;        }        pkt1 = q->first_pkt;        if (pkt1) {            q->first_pkt = pkt1->next;            if (!q->first_pkt)                q->last_pkt = NULL;            q->nb_packets--;            q->size -= pkt1->pkt.size;            *pkt = pkt1->pkt;            av_free(pkt1);            ret = 1;            break;        } else if (!block) {            ret = 0;            break;        } else {            SDL_CondWait(q->cond, q->mutex);        }    }    SDL_UnlockMutex(q->mutex);    return ret;}int audio_decode_frame(AVCodecContext *aCodecCtx, uint8_t *audio_buf,        int buf_size) {    static AVPacket pkt;    static uint8_t *audio_pkt_data =http://www.mamicode.com/ NULL;    static int audio_pkt_size = 0;    static AVFrame frame;    int len1, data_size = 0;    for (;;) {        while (audio_pkt_size > 0) {            int got_frame = 0;            len1 = avcodec_decode_audio4(aCodecCtx, &frame, &got_frame, &pkt);            if (len1 < 0) {                /* if error, skip frame */                audio_pkt_size = 0;                break;            }            audio_pkt_data += len1;            audio_pkt_size -= len1;            if (got_frame) {                data_size = frame.linesize[0];                /*                 data_size = av_samples_get_buffer_size(NULL,                 aCodecCtx->channels, frame.nb_samples,                 aCodecCtx->sample_fmt, 1);                 */                memcpy(audio_buf, frame.data[0], data_size);            }            if (data_size <= 0) {                /* No data yet, get more frames */                continue;            }            /* We have data, return it and come back for more later */            return data_size;        }        if (pkt.data)            av_free_packet(&pkt);        if (quit) {            return -1;        }        if (packet_queue_get(&audioq, &pkt, 1) < 0) {            return -1;        }        audio_pkt_data = pkt.data;        audio_pkt_size = pkt.size;    }    return 0;}void audio_callback(void *userdata, Uint8 *stream, int len) {    AVCodecContext *aCodecCtx = (AVCodecContext *) userdata;    int len1, audio_size;    static uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];    static unsigned int audio_buf_size = 0;    static unsigned int audio_buf_index = 0;    while (len > 0) {        if (audio_buf_index >= audio_buf_size) {            /* We have already sent all our data; get more */            audio_size = audio_decode_frame(aCodecCtx, audio_buf,                    sizeof(audio_buf));            if (audio_size < 0) {                /* If error, output silence */                audio_buf_size = 1024; // arbitrary?                memset(audio_buf, 0, audio_buf_size);            } else {                audio_buf_size = audio_size;            }            audio_buf_index = 0;        }        len1 = audio_buf_size - audio_buf_index;        if (len1 > len)            len1 = len;        memcpy(stream, (uint8_t *) audio_buf + audio_buf_index, len1);        len -= len1;        stream += len1;        audio_buf_index += len1;    }}int main(int argc, char* args[]) {    AVFormatContext *pFormatCtx = NULL;    int i, videoStream, audioStream;    AVCodecContext *pCodecCtx;    AVCodec *pCodec;    AVFrame *pFrame;    AVPacket packet;    struct SwsContext * pSwsCtx;    int frameFinished;    AVCodecContext *aCodecCtx;    AVCodec *aCodec;    SDL_Overlay *bmp;    SDL_Surface *screen;    SDL_Rect rect;    SDL_Event event;    SDL_AudioSpec wanted_spec, spec;    return EXIT_SUCCESS;}

  八、注册初始化与打开视频相关函数

/* ============================================================================ Name        : VideoDecodeTutorial2_1.c Author      : clarck Version     : Copyright   : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include "SDL/SDL.h"#include "SDL/SDL_thread.h"#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavutil/pixfmt.h"#include "libswscale/swscale.h"#ifdef __MINGW32__#undef main /* Prevents SDL from overriding main() */#endif#define SDL_AUDIO_BUFFER_SIZE 1024#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audiotypedef struct PacketQueue {    AVPacketList *first_pkt, *last_pkt;    int nb_packets;    int size;    SDL_mutex *mutex;    SDL_cond *cond;} PacketQueue;PacketQueue audioq;int quit = 0;void packet_queue_init(PacketQueue *q) {    memset(q, 0, sizeof(PacketQueue));    q->mutex = SDL_CreateMutex();    q->cond = SDL_CreateCond();}int packet_queue_put(PacketQueue *q, AVPacket *pkt) {    AVPacketList *pkt1;    if (av_dup_packet(pkt) < 0) {        return -1;    }    pkt1 = av_malloc(sizeof(AVPacketList));    if (!pkt1)        return -1;    pkt1->pkt = *pkt;    pkt1->next = NULL;    SDL_LockMutex(q->mutex);    if (!q->last_pkt)        q->first_pkt = pkt1;    else        q->last_pkt->next = pkt1;    q->last_pkt = pkt1;    q->nb_packets++;    q->size += pkt1->pkt.size;    SDL_CondSignal(q->cond);    SDL_UnlockMutex(q->mutex);    return 0;}static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) {    AVPacketList *pkt1;    int ret;    SDL_LockMutex(q->mutex);    for (;;) {        if (quit) {            ret = -1;            break;        }        pkt1 = q->first_pkt;        if (pkt1) {            q->first_pkt = pkt1->next;            if (!q->first_pkt)                q->last_pkt = NULL;            q->nb_packets--;            q->size -= pkt1->pkt.size;            *pkt = pkt1->pkt;            av_free(pkt1);            ret = 1;            break;        } else if (!block) {            ret = 0;            break;        } else {            SDL_CondWait(q->cond, q->mutex);        }    }    SDL_UnlockMutex(q->mutex);    return ret;}int audio_decode_frame(AVCodecContext *aCodecCtx, uint8_t *audio_buf,        int buf_size) {    static AVPacket pkt;    static uint8_t *audio_pkt_data =http://www.mamicode.com/ NULL;    static int audio_pkt_size = 0;    static AVFrame frame;    int len1, data_size = 0;    for (;;) {        while (audio_pkt_size > 0) {            int got_frame = 0;            len1 = avcodec_decode_audio4(aCodecCtx, &frame, &got_frame, &pkt);            if (len1 < 0) {                /* if error, skip frame */                audio_pkt_size = 0;                break;            }            audio_pkt_data += len1;            audio_pkt_size -= len1;            if (got_frame) {                data_size = frame.linesize[0];                /*                 data_size = av_samples_get_buffer_size(NULL,                 aCodecCtx->channels, frame.nb_samples,                 aCodecCtx->sample_fmt, 1);                 */                memcpy(audio_buf, frame.data[0], data_size);            }            if (data_size <= 0) {                /* No data yet, get more frames */                continue;            }            /* We have data, return it and come back for more later */            return data_size;        }        if (pkt.data)            av_free_packet(&pkt);        if (quit) {            return -1;        }        if (packet_queue_get(&audioq, &pkt, 1) < 0) {            return -1;        }        audio_pkt_data = pkt.data;        audio_pkt_size = pkt.size;    }    return 0;}void audio_callback(void *userdata, Uint8 *stream, int len) {    AVCodecContext *aCodecCtx = (AVCodecContext *) userdata;    int len1, audio_size;    static uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];    static unsigned int audio_buf_size = 0;    static unsigned int audio_buf_index = 0;    while (len > 0) {        if (audio_buf_index >= audio_buf_size) {            /* We have already sent all our data; get more */            audio_size = audio_decode_frame(aCodecCtx, audio_buf,                    sizeof(audio_buf));            if (audio_size < 0) {                /* If error, output silence */                audio_buf_size = 1024; // arbitrary?                memset(audio_buf, 0, audio_buf_size);            } else {                audio_buf_size = audio_size;            }            audio_buf_index = 0;        }        len1 = audio_buf_size - audio_buf_index;        if (len1 > len)            len1 = len;        memcpy(stream, (uint8_t *) audio_buf + audio_buf_index, len1);        len -= len1;        stream += len1;        audio_buf_index += len1;    }}int main(int argc, char* args[]) {    AVFormatContext *pFormatCtx = NULL;    int i, videoStream, audioStream;    AVCodecContext *pCodecCtx;    AVCodec *pCodec;    AVFrame *pFrame;    AVPacket packet;    struct SwsContext * pSwsCtx;    int frameFinished;    AVCodecContext *aCodecCtx;    AVCodec *aCodec;    SDL_Overlay *bmp;    SDL_Surface *screen;    SDL_Rect rect;    SDL_Event event;    SDL_AudioSpec wanted_spec, spec;    char filePath[] = "./src/a.mp4";    // Register all formats and codecs    av_register_all();    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());        exit(1);    }    // Open video file    if (avformat_open_input(&pFormatCtx, filePath, NULL, NULL) != 0)        return -1; // Couldn‘t open file    // Retrieve stream information    if (avformat_find_stream_info(pFormatCtx, NULL) < 0)        return -1; // Couldn‘t find stream information    // Dump information about file onto standard error    av_dump_format(pFormatCtx, 0, filePath, 0);        return EXIT_SUCCESS;}

  九、找到第一条视频流和音频流

/* ============================================================================ Name        : VideoDecodeTutorial2_1.c Author      : clarck Version     : Copyright   : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include "SDL/SDL.h"#include "SDL/SDL_thread.h"#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavutil/pixfmt.h"#include "libswscale/swscale.h"#ifdef __MINGW32__#undef main /* Prevents SDL from overriding main() */#endif#define SDL_AUDIO_BUFFER_SIZE 1024#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audiotypedef struct PacketQueue {    AVPacketList *first_pkt, *last_pkt;    int nb_packets;    int size;    SDL_mutex *mutex;    SDL_cond *cond;} PacketQueue;PacketQueue audioq;int quit = 0;void packet_queue_init(PacketQueue *q) {    memset(q, 0, sizeof(PacketQueue));    q->mutex = SDL_CreateMutex();    q->cond = SDL_CreateCond();}int packet_queue_put(PacketQueue *q, AVPacket *pkt) {    AVPacketList *pkt1;    if (av_dup_packet(pkt) < 0) {        return -1;    }    pkt1 = av_malloc(sizeof(AVPacketList));    if (!pkt1)        return -1;    pkt1->pkt = *pkt;    pkt1->next = NULL;    SDL_LockMutex(q->mutex);    if (!q->last_pkt)        q->first_pkt = pkt1;    else        q->last_pkt->next = pkt1;    q->last_pkt = pkt1;    q->nb_packets++;    q->size += pkt1->pkt.size;    SDL_CondSignal(q->cond);    SDL_UnlockMutex(q->mutex);    return 0;}static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) {    AVPacketList *pkt1;    int ret;    SDL_LockMutex(q->mutex);    for (;;) {        if (quit) {            ret = -1;            break;        }        pkt1 = q->first_pkt;        if (pkt1) {            q->first_pkt = pkt1->next;            if (!q->first_pkt)                q->last_pkt = NULL;            q->nb_packets--;            q->size -= pkt1->pkt.size;            *pkt = pkt1->pkt;            av_free(pkt1);            ret = 1;            break;        } else if (!block) {            ret = 0;            break;        } else {            SDL_CondWait(q->cond, q->mutex);        }    }    SDL_UnlockMutex(q->mutex);    return ret;}int audio_decode_frame(AVCodecContext *aCodecCtx, uint8_t *audio_buf,        int buf_size) {    static AVPacket pkt;    static uint8_t *audio_pkt_data =http://www.mamicode.com/ NULL;    static int audio_pkt_size = 0;    static AVFrame frame;    int len1, data_size = 0;    for (;;) {        while (audio_pkt_size > 0) {            int got_frame = 0;            len1 = avcodec_decode_audio4(aCodecCtx, &frame, &got_frame, &pkt);            if (len1 < 0) {                /* if error, skip frame */                audio_pkt_size = 0;                break;            }            audio_pkt_data += len1;            audio_pkt_size -= len1;            if (got_frame) {                data_size = frame.linesize[0];                /*                 data_size = av_samples_get_buffer_size(NULL,                 aCodecCtx->channels, frame.nb_samples,                 aCodecCtx->sample_fmt, 1);                 */                memcpy(audio_buf, frame.data[0], data_size);            }            if (data_size <= 0) {                /* No data yet, get more frames */                continue;            }            /* We have data, return it and come back for more later */            return data_size;        }        if (pkt.data)            av_free_packet(&pkt);        if (quit) {            return -1;        }        if (packet_queue_get(&audioq, &pkt, 1) < 0) {            return -1;        }        audio_pkt_data = pkt.data;        audio_pkt_size = pkt.size;    }    return 0;}void audio_callback(void *userdata, Uint8 *stream, int len) {    AVCodecContext *aCodecCtx = (AVCodecContext *) userdata;    int len1, audio_size;    static uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];    static unsigned int audio_buf_size = 0;    static unsigned int audio_buf_index = 0;    while (len > 0) {        if (audio_buf_index >= audio_buf_size) {            /* We have already sent all our data; get more */            audio_size = audio_decode_frame(aCodecCtx, audio_buf,                    sizeof(audio_buf));            if (audio_size < 0) {                /* If error, output silence */                audio_buf_size = 1024; // arbitrary?                memset(audio_buf, 0, audio_buf_size);            } else {                audio_buf_size = audio_size;            }            audio_buf_index = 0;        }        len1 = audio_buf_size - audio_buf_index;        if (len1 > len)            len1 = len;        memcpy(stream, (uint8_t *) audio_buf + audio_buf_index, len1);        len -= len1;        stream += len1;        audio_buf_index += len1;    }}int main(int argc, char* args[]) {    AVFormatContext *pFormatCtx = NULL;    int i, videoStream, audioStream;    AVCodecContext *pCodecCtx;    AVCodec *pCodec;    AVFrame *pFrame;    AVPacket packet;    struct SwsContext * pSwsCtx;    int frameFinished;    AVCodecContext *aCodecCtx;    AVCodec *aCodec;    SDL_Overlay *bmp;    SDL_Surface *screen;    SDL_Rect rect;    SDL_Event event;    SDL_AudioSpec wanted_spec, spec;    char filePath[] = "./src/a.mp4";    // Register all formats and codecs    av_register_all();    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());        exit(1);    }    // Open video file    if (avformat_open_input(&pFormatCtx, filePath, NULL, NULL) != 0)        return -1; // Couldn‘t open file    // Retrieve stream information    if (avformat_find_stream_info(pFormatCtx, NULL) < 0)        return -1; // Couldn‘t find stream information    // Dump information about file onto standard error    av_dump_format(pFormatCtx, 0, filePath, 0);    // Find the first video stream    videoStream = -1;    audioStream = -1;    for (i = 0; i < pFormatCtx->nb_streams; i++) {        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO                && videoStream < 0) {            videoStream = i;        }        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO                && audioStream < 0) {            audioStream = i;        }    }    if (videoStream == -1)        return -1; // Didn‘t find a video stream    if (audioStream == -1)        return -1;    return EXIT_SUCCESS;}

  十、注册音频相关设置到SDL_AudioSpec中

/* ============================================================================ Name        : VideoDecodeTutorial2_1.c Author      : clarck Version     : Copyright   : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include "SDL/SDL.h"#include "SDL/SDL_thread.h"#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavutil/pixfmt.h"#include "libswscale/swscale.h"#ifdef __MINGW32__#undef main /* Prevents SDL from overriding main() */#endif#define SDL_AUDIO_BUFFER_SIZE 1024#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audiotypedef struct PacketQueue {    AVPacketList *first_pkt, *last_pkt;    int nb_packets;    int size;    SDL_mutex *mutex;    SDL_cond *cond;} PacketQueue;PacketQueue audioq;int quit = 0;void packet_queue_init(PacketQueue *q) {    memset(q, 0, sizeof(PacketQueue));    q->mutex = SDL_CreateMutex();    q->cond = SDL_CreateCond();}int packet_queue_put(PacketQueue *q, AVPacket *pkt) {    AVPacketList *pkt1;    if (av_dup_packet(pkt) < 0) {        return -1;    }    pkt1 = av_malloc(sizeof(AVPacketList));    if (!pkt1)        return -1;    pkt1->pkt = *pkt;    pkt1->next = NULL;    SDL_LockMutex(q->mutex);    if (!q->last_pkt)        q->first_pkt = pkt1;    else        q->last_pkt->next = pkt1;    q->last_pkt = pkt1;    q->nb_packets++;    q->size += pkt1->pkt.size;    SDL_CondSignal(q->cond);    SDL_UnlockMutex(q->mutex);    return 0;}static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) {    AVPacketList *pkt1;    int ret;    SDL_LockMutex(q->mutex);    for (;;) {        if (quit) {            ret = -1;            break;        }        pkt1 = q->first_pkt;        if (pkt1) {            q->first_pkt = pkt1->next;            if (!q->first_pkt)                q->last_pkt = NULL;            q->nb_packets--;            q->size -= pkt1->pkt.size;            *pkt = pkt1->pkt;            av_free(pkt1);            ret = 1;            break;        } else if (!block) {            ret = 0;            break;        } else {            SDL_CondWait(q->cond, q->mutex);        }    }    SDL_UnlockMutex(q->mutex);    return ret;}int audio_decode_frame(AVCodecContext *aCodecCtx, uint8_t *audio_buf,        int buf_size) {    static AVPacket pkt;    static uint8_t *audio_pkt_data =http://www.mamicode.com/ NULL;    static int audio_pkt_size = 0;    static AVFrame frame;    int len1, data_size = 0;    for (;;) {        while (audio_pkt_size > 0) {            int got_frame = 0;            len1 = avcodec_decode_audio4(aCodecCtx, &frame, &got_frame, &pkt);            if (len1 < 0) {                /* if error, skip frame */                audio_pkt_size = 0;                break;            }            audio_pkt_data += len1;            audio_pkt_size -= len1;            if (got_frame) {                data_size = frame.linesize[0];                /*                 data_size = av_samples_get_buffer_size(NULL,                 aCodecCtx->channels, frame.nb_samples,                 aCodecCtx->sample_fmt, 1);                 */                memcpy(audio_buf, frame.data[0], data_size);            }            if (data_size <= 0) {                /* No data yet, get more frames */                continue;            }            /* We have data, return it and come back for more later */            return data_size;        }        if (pkt.data)            av_free_packet(&pkt);        if (quit) {            return -1;        }        if (packet_queue_get(&audioq, &pkt, 1) < 0) {            return -1;        }        audio_pkt_data = pkt.data;        audio_pkt_size = pkt.size;    }    return 0;}void audio_callback(void *userdata, Uint8 *stream, int len) {    AVCodecContext *aCodecCtx = (AVCodecContext *) userdata;    int len1, audio_size;    static uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];    static unsigned int audio_buf_size = 0;    static unsigned int audio_buf_index = 0;    while (len > 0) {        if (audio_buf_index >= audio_buf_size) {            /* We have already sent all our data; get more */            audio_size = audio_decode_frame(aCodecCtx, audio_buf,                    sizeof(audio_buf));            if (audio_size < 0) {                /* If error, output silence */                audio_buf_size = 1024; // arbitrary?                memset(audio_buf, 0, audio_buf_size);            } else {                audio_buf_size = audio_size;            }            audio_buf_index = 0;        }        len1 = audio_buf_size - audio_buf_index;        if (len1 > len)            len1 = len;        memcpy(stream, (uint8_t *) audio_buf + audio_buf_index, len1);        len -= len1;        stream += len1;        audio_buf_index += len1;    }}int main(int argc, char* args[]) {    AVFormatContext *pFormatCtx = NULL;    int i, videoStream, audioStream;    AVCodecContext *pCodecCtx;    AVCodec *pCodec;    AVFrame *pFrame;    AVPacket packet;    struct SwsContext * pSwsCtx;    int frameFinished;    AVCodecContext *aCodecCtx;    AVCodec *aCodec;    SDL_Overlay *bmp;    SDL_Surface *screen;    SDL_Rect rect;    SDL_Event event;    SDL_AudioSpec wanted_spec, spec;    char filePath[] = "./src/a.mp4";    // Register all formats and codecs    av_register_all();    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());        exit(1);    }    // Open video file    if (avformat_open_input(&pFormatCtx, filePath, NULL, NULL) != 0)        return -1; // Couldn‘t open file    // Retrieve stream information    if (avformat_find_stream_info(pFormatCtx, NULL) < 0)        return -1; // Couldn‘t find stream information    // Dump information about file onto standard error    av_dump_format(pFormatCtx, 0, filePath, 0);    // Find the first video stream    videoStream = -1;    audioStream = -1;    for (i = 0; i < pFormatCtx->nb_streams; i++) {        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO                && videoStream < 0) {            videoStream = i;        }        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO                && audioStream < 0) {            audioStream = i;        }    }    if (videoStream == -1)        return -1; // Didn‘t find a video stream    if (audioStream == -1)        return -1;    aCodecCtx = pFormatCtx->streams[audioStream]->codec;    // Set audio settings from codec info    wanted_spec.freq = aCodecCtx->sample_rate;    wanted_spec.format = AUDIO_S16SYS;    wanted_spec.channels = aCodecCtx->channels;    wanted_spec.silence = 0;    wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;    wanted_spec.callback = audio_callback;    wanted_spec.userdata = aCodecCtx;    return EXIT_SUCCESS;}

  十一、初始化音频数据队列并打开音频设备

/* ============================================================================ Name        : VideoDecodeTutorial2_1.c Author      : clarck Version     : Copyright   : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include "SDL/SDL.h"#include "SDL/SDL_thread.h"#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavutil/pixfmt.h"#include "libswscale/swscale.h"#ifdef __MINGW32__#undef main /* Prevents SDL from overriding main() */#endif#define SDL_AUDIO_BUFFER_SIZE 1024#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audiotypedef struct PacketQueue {    AVPacketList *first_pkt, *last_pkt;    int nb_packets;    int size;    SDL_mutex *mutex;    SDL_cond *cond;} PacketQueue;PacketQueue audioq;int quit = 0;void packet_queue_init(PacketQueue *q) {    memset(q, 0, sizeof(PacketQueue));    q->mutex = SDL_CreateMutex();    q->cond = SDL_CreateCond();}int packet_queue_put(PacketQueue *q, AVPacket *pkt) {    AVPacketList *pkt1;    if (av_dup_packet(pkt) < 0) {        return -1;    }    pkt1 = av_malloc(sizeof(AVPacketList));    if (!pkt1)        return -1;    pkt1->pkt = *pkt;    pkt1->next = NULL;    SDL_LockMutex(q->mutex);    if (!q->last_pkt)        q->first_pkt = pkt1;    else        q->last_pkt->next = pkt1;    q->last_pkt = pkt1;    q->nb_packets++;    q->size += pkt1->pkt.size;    SDL_CondSignal(q->cond);    SDL_UnlockMutex(q->mutex);    return 0;}static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) {    AVPacketList *pkt1;    int ret;    SDL_LockMutex(q->mutex);    for (;;) {        if (quit) {            ret = -1;            break;        }        pkt1 = q->first_pkt;        if (pkt1) {            q->first_pkt = pkt1->next;            if (!q->first_pkt)                q->last_pkt = NULL;            q->nb_packets--;            q->size -= pkt1->pkt.size;            *pkt = pkt1->pkt;            av_free(pkt1);            ret = 1;            break;        } else if (!block) {            ret = 0;            break;        } else {            SDL_CondWait(q->cond, q->mutex);        }    }    SDL_UnlockMutex(q->mutex);    return ret;}int audio_decode_frame(AVCodecContext *aCodecCtx, uint8_t *audio_buf,        int buf_size) {    static AVPacket pkt;    static uint8_t *audio_pkt_data =http://www.mamicode.com/ NULL;    static int audio_pkt_size = 0;    static AVFrame frame;    int len1, data_size = 0;    for (;;) {        while (audio_pkt_size > 0) {            int got_frame = 0;            len1 = avcodec_decode_audio4(aCodecCtx, &frame, &got_frame, &pkt);            if (len1 < 0) {                /* if error, skip frame */                audio_pkt_size = 0;                break;            }            audio_pkt_data += len1;            audio_pkt_size -= len1;            if (got_frame) {                data_size = frame.linesize[0];                /*                 data_size = av_samples_get_buffer_size(NULL,                 aCodecCtx->channels, frame.nb_samples,                 aCodecCtx->sample_fmt, 1);                 */                memcpy(audio_buf, frame.data[0], data_size);            }            if (data_size <= 0) {                /* No data yet, get more frames */                continue;            }            /* We have data, return it and come back for more later */            return data_size;        }        if (pkt.data)            av_free_packet(&pkt);        if (quit) {            return -1;        }        if (packet_queue_get(&audioq, &pkt, 1) < 0) {            return -1;        }        audio_pkt_data = pkt.data;        audio_pkt_size = pkt.size;    }    return 0;}void audio_callback(void *userdata, Uint8 *stream, int len) {    AVCodecContext *aCodecCtx = (AVCodecContext *) userdata;    int len1, audio_size;    static uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];    static unsigned int audio_buf_size = 0;    static unsigned int audio_buf_index = 0;    while (len > 0) {        if (audio_buf_index >= audio_buf_size) {            /* We have already sent all our data; get more */            audio_size = audio_decode_frame(aCodecCtx, audio_buf,                    sizeof(audio_buf));            if (audio_size < 0) {                /* If error, output silence */                audio_buf_size = 1024; // arbitrary?                memset(audio_buf, 0, audio_buf_size);            } else {                audio_buf_size = audio_size;            }            audio_buf_index = 0;        }        len1 = audio_buf_size - audio_buf_index;        if (len1 > len)            len1 = len;        memcpy(stream, (uint8_t *) audio_buf + audio_buf_index, len1);        len -= len1;        stream += len1;        audio_buf_index += len1;    }}int main(int argc, char* args[]) {    AVFormatContext *pFormatCtx = NULL;    int i, videoStream, audioStream;    AVCodecContext *pCodecCtx;    AVCodec *pCodec;    AVFrame *pFrame;    AVPacket packet;    struct SwsContext * pSwsCtx;    int frameFinished;    AVCodecContext *aCodecCtx;    AVCodec *aCodec;    SDL_Overlay *bmp;    SDL_Surface *screen;    SDL_Rect rect;    SDL_Event event;    SDL_AudioSpec wanted_spec, spec;    char filePath[] = "./src/a.mp4";    // Register all formats and codecs    av_register_all();    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());        exit(1);    }    // Open video file    if (avformat_open_input(&pFormatCtx, filePath, NULL, NULL) != 0)        return -1; // Couldn‘t open file    // Retrieve stream information    if (avformat_find_stream_info(pFormatCtx, NULL) < 0)        return -1; // Couldn‘t find stream information    // Dump information about file onto standard error    av_dump_format(pFormatCtx, 0, filePath, 0);    // Find the first video stream    videoStream = -1;    audioStream = -1;    for (i = 0; i < pFormatCtx->nb_streams; i++) {        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO                && videoStream < 0) {            videoStream = i;        }        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO                && audioStream < 0) {            audioStream = i;        }    }    if (videoStream == -1)        return -1; // Didn‘t find a video stream    if (audioStream == -1)        return -1;    aCodecCtx = pFormatCtx->streams[audioStream]->codec;    // Set audio settings from codec info    wanted_spec.freq = aCodecCtx->sample_rate;    wanted_spec.format = AUDIO_S16SYS;    wanted_spec.channels = aCodecCtx->channels;    wanted_spec.silence = 0;    wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;    wanted_spec.callback = audio_callback;    wanted_spec.userdata = aCodecCtx;    if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {        fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());        return -1;    }    aCodec = avcodec_find_decoder(aCodecCtx->codec_id);    if (!aCodec) {        fprintf(stderr, "Unsupported codec!\n");        return -1;    }    avcodec_open2(aCodecCtx, aCodec, NULL);    // audio_st = pFormatCtx->streams[index]    packet_queue_init(&audioq);    SDL_PauseAudio(0);    return EXIT_SUCCESS;}

  十二、初始化与Video相关的环境变量

/* ============================================================================ Name        : VideoDecodeTutorial2_1.c Author      : clarck Version     : Copyright   : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include "SDL/SDL.h"#include "SDL/SDL_thread.h"#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavutil/pixfmt.h"#include "libswscale/swscale.h"#ifdef __MINGW32__#undef main /* Prevents SDL from overriding main() */#endif#define SDL_AUDIO_BUFFER_SIZE 1024#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audiotypedef struct PacketQueue {    AVPacketList *first_pkt, *last_pkt;    int nb_packets;    int size;    SDL_mutex *mutex;    SDL_cond *cond;} PacketQueue;PacketQueue audioq;int quit = 0;void packet_queue_init(PacketQueue *q) {    memset(q, 0, sizeof(PacketQueue));    q->mutex = SDL_CreateMutex();    q->cond = SDL_CreateCond();}int packet_queue_put(PacketQueue *q, AVPacket *pkt) {    AVPacketList *pkt1;    if (av_dup_packet(pkt) < 0) {        return -1;    }    pkt1 = av_malloc(sizeof(AVPacketList));    if (!pkt1)        return -1;    pkt1->pkt = *pkt;    pkt1->next = NULL;    SDL_LockMutex(q->mutex);    if (!q->last_pkt)        q->first_pkt = pkt1;    else        q->last_pkt->next = pkt1;    q->last_pkt = pkt1;    q->nb_packets++;    q->size += pkt1->pkt.size;    SDL_CondSignal(q->cond);    SDL_UnlockMutex(q->mutex);    return 0;}static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) {    AVPacketList *pkt1;    int ret;    SDL_LockMutex(q->mutex);    for (;;) {        if (quit) {            ret = -1;            break;        }        pkt1 = q->first_pkt;        if (pkt1) {            q->first_pkt = pkt1->next;            if (!q->first_pkt)                q->last_pkt = NULL;            q->nb_packets--;            q->size -= pkt1->pkt.size;            *pkt = pkt1->pkt;            av_free(pkt1);            ret = 1;            break;        } else if (!block) {            ret = 0;            break;        } else {            SDL_CondWait(q->cond, q->mutex);        }    }    SDL_UnlockMutex(q->mutex);    return ret;}int audio_decode_frame(AVCodecContext *aCodecCtx, uint8_t *audio_buf,        int buf_size) {    static AVPacket pkt;    static uint8_t *audio_pkt_data =http://www.mamicode.com/ NULL;    static int audio_pkt_size = 0;    static AVFrame frame;    int len1, data_size = 0;    for (;;) {        while (audio_pkt_size > 0) {            int got_frame = 0;            len1 = avcodec_decode_audio4(aCodecCtx, &frame, &got_frame, &pkt);            if (len1 < 0) {                /* if error, skip frame */                audio_pkt_size = 0;                break;            }            audio_pkt_data += len1;            audio_pkt_size -= len1;            if (got_frame) {                data_size = frame.linesize[0];                /*                 data_size = av_samples_get_buffer_size(NULL,                 aCodecCtx->channels, frame.nb_samples,                 aCodecCtx->sample_fmt, 1);                 */                memcpy(audio_buf, frame.data[0], data_size);            }            if (data_size <= 0) {                /* No data yet, get more frames */                continue;            }            /* We have data, return it and come back for more later */            return data_size;        }        if (pkt.data)            av_free_packet(&pkt);        if (quit) {            return -1;        }        if (packet_queue_get(&audioq, &pkt, 1) < 0) {            return -1;        }        audio_pkt_data = pkt.data;        audio_pkt_size = pkt.size;    }    return 0;}void audio_callback(void *userdata, Uint8 *stream, int len) {    AVCodecContext *aCodecCtx = (AVCodecContext *) userdata;    int len1, audio_size;    static uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];    static unsigned int audio_buf_size = 0;    static unsigned int audio_buf_index = 0;    while (len > 0) {        if (audio_buf_index >= audio_buf_size) {            /* We have already sent all our data; get more */            audio_size = audio_decode_frame(aCodecCtx, audio_buf,                    sizeof(audio_buf));            if (audio_size < 0) {                /* If error, output silence */                audio_buf_size = 1024; // arbitrary?                memset(audio_buf, 0, audio_buf_size);            } else {                audio_buf_size = audio_size;            }            audio_buf_index = 0;        }        len1 = audio_buf_size - audio_buf_index;        if (len1 > len)            len1 = len;        memcpy(stream, (uint8_t *) audio_buf + audio_buf_index, len1);        len -= len1;        stream += len1;        audio_buf_index += len1;    }}int main(int argc, char* args[]) {    AVFormatContext *pFormatCtx = NULL;    int i, videoStream, audioStream;    AVCodecContext *pCodecCtx;    AVCodec *pCodec;    AVFrame *pFrame;    AVPacket packet;    struct SwsContext * pSwsCtx;    int frameFinished;    AVCodecContext *aCodecCtx;    AVCodec *aCodec;    SDL_Overlay *bmp;    SDL_Surface *screen;    SDL_Rect rect;    SDL_Event event;    SDL_AudioSpec wanted_spec, spec;    char filePath[] = "./src/a.mp4";    // Register all formats and codecs    av_register_all();    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());        exit(1);    }    // Open video file    if (avformat_open_input(&pFormatCtx, filePath, NULL, NULL) != 0)        return -1; // Couldn‘t open file    // Retrieve stream information    if (avformat_find_stream_info(pFormatCtx, NULL) < 0)        return -1; // Couldn‘t find stream information    // Dump information about file onto standard error    av_dump_format(pFormatCtx, 0, filePath, 0);    // Find the first video stream    videoStream = -1;    audioStream = -1;    for (i = 0; i < pFormatCtx->nb_streams; i++) {        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO                && videoStream < 0) {            videoStream = i;        }        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO                && audioStream < 0) {            audioStream = i;        }    }    if (videoStream == -1)        return -1; // Didn‘t find a video stream    if (audioStream == -1)        return -1;    aCodecCtx = pFormatCtx->streams[audioStream]->codec;    // Set audio settings from codec info    wanted_spec.freq = aCodecCtx->sample_rate;    wanted_spec.format = AUDIO_S16SYS;    wanted_spec.channels = aCodecCtx->channels;    wanted_spec.silence = 0;    wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;    wanted_spec.callback = audio_callback;    wanted_spec.userdata = aCodecCtx;    if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {        fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());        return -1;    }    aCodec = avcodec_find_decoder(aCodecCtx->codec_id);    if (!aCodec) {        fprintf(stderr, "Unsupported codec!\n");        return -1;    }    avcodec_open2(aCodecCtx, aCodec, NULL);    // audio_st = pFormatCtx->streams[index]    packet_queue_init(&audioq);    SDL_PauseAudio(0);    // Get a pointer to the codec context for the video stream    pCodecCtx = pFormatCtx->streams[videoStream]->codec;    // Find the decoder for the video stream    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);    if (pCodec == NULL) {        fprintf(stderr, "Unsupported codec!\n");        return -1; // Codec not found    }    // Open codec    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)        return -1; // Could not open codec    // Allocate video frame    pFrame = avcodec_alloc_frame();    pSwsCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height,            pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,            AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL);    return EXIT_SUCCESS;}

  十三、初始化视频输出环境

/* ============================================================================ Name        : VideoDecodeTutorial2_1.c Author      : clarck Version     : Copyright   : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include "SDL/SDL.h"#include "SDL/SDL_thread.h"#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavutil/pixfmt.h"#include "libswscale/swscale.h"#ifdef __MINGW32__#undef main /* Prevents SDL from overriding main() */#endif#define SDL_AUDIO_BUFFER_SIZE 1024#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audiotypedef struct PacketQueue {    AVPacketList *first_pkt, *last_pkt;    int nb_packets;    int size;    SDL_mutex *mutex;    SDL_cond *cond;} PacketQueue;PacketQueue audioq;int quit = 0;void packet_queue_init(PacketQueue *q) {    memset(q, 0, sizeof(PacketQueue));    q->mutex = SDL_CreateMutex();    q->cond = SDL_CreateCond();}int packet_queue_put(PacketQueue *q, AVPacket *pkt) {    AVPacketList *pkt1;    if (av_dup_packet(pkt) < 0) {        return -1;    }    pkt1 = av_malloc(sizeof(AVPacketList));    if (!pkt1)        return -1;    pkt1->pkt = *pkt;    pkt1->next = NULL;    SDL_LockMutex(q->mutex);    if (!q->last_pkt)        q->first_pkt = pkt1;    else        q->last_pkt->next = pkt1;    q->last_pkt = pkt1;    q->nb_packets++;    q->size += pkt1->pkt.size;    SDL_CondSignal(q->cond);    SDL_UnlockMutex(q->mutex);    return 0;}static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) {    AVPacketList *pkt1;    int ret;    SDL_LockMutex(q->mutex);    for (;;) {        if (quit) {            ret = -1;            break;        }        pkt1 = q->first_pkt;        if (pkt1) {            q->first_pkt = pkt1->next;            if (!q->first_pkt)                q->last_pkt = NULL;            q->nb_packets--;            q->size -= pkt1->pkt.size;            *pkt = pkt1->pkt;            av_free(pkt1);            ret = 1;            break;        } else if (!block) {            ret = 0;            break;        } else {            SDL_CondWait(q->cond, q->mutex);        }    }    SDL_UnlockMutex(q->mutex);    return ret;}int audio_decode_frame(AVCodecContext *aCodecCtx, uint8_t *audio_buf,        int buf_size) {    static AVPacket pkt;    static uint8_t *audio_pkt_data =http://www.mamicode.com/ NULL;    static int audio_pkt_size = 0;    static AVFrame frame;    int len1, data_size = 0;    for (;;) {        while (audio_pkt_size > 0) {            int got_frame = 0;            len1 = avcodec_decode_audio4(aCodecCtx, &frame, &got_frame, &pkt);            if (len1 < 0) {                /* if error, skip frame */                audio_pkt_size = 0;                break;            }            audio_pkt_data += len1;            audio_pkt_size -= len1;            if (got_frame) {                data_size = frame.linesize[0];                /*                 data_size = av_samples_get_buffer_size(NULL,                 aCodecCtx->channels, frame.nb_samples,                 aCodecCtx->sample_fmt, 1);                 */                memcpy(audio_buf, frame.data[0], data_size);            }            if (data_size <= 0) {                /* No data yet, get more frames */                continue;            }            /* We have data, return it and come back for more later */            return data_size;        }        if (pkt.data)            av_free_packet(&pkt);        if (quit) {            return -1;        }        if (packet_queue_get(&audioq, &pkt, 1) < 0) {            return -1;        }        audio_pkt_data = pkt.data;        audio_pkt_size = pkt.size;    }    return 0;}void audio_callback(void *userdata, Uint8 *stream, int len) {    AVCodecContext *aCodecCtx = (AVCodecContext *) userdata;    int len1, audio_size;    static uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];    static unsigned int audio_buf_size = 0;    static unsigned int audio_buf_index = 0;    while (len > 0) {        if (audio_buf_index >= audio_buf_size) {            /* We have already sent all our data; get more */            audio_size = audio_decode_frame(aCodecCtx, audio_buf,                    sizeof(audio_buf));            if (audio_size < 0) {                /* If error, output silence */                audio_buf_size = 1024; // arbitrary?                memset(audio_buf, 0, audio_buf_size);            } else {                audio_buf_size = audio_size;            }            audio_buf_index = 0;        }        len1 = audio_buf_size - audio_buf_index;        if (len1 > len)            len1 = len;        memcpy(stream, (uint8_t *) audio_buf + audio_buf_index, len1);        len -= len1;        stream += len1;        audio_buf_index += len1;    }}int main(int argc, char* args[]) {    AVFormatContext *pFormatCtx = NULL;    int i, videoStream, audioStream;    AVCodecContext *pCodecCtx;    AVCodec *pCodec;    AVFrame *pFrame;    AVPacket packet;    struct SwsContext * pSwsCtx;    int frameFinished;    AVCodecContext *aCodecCtx;    AVCodec *aCodec;    SDL_Overlay *bmp;    SDL_Surface *screen;    SDL_Rect rect;    SDL_Event event;    SDL_AudioSpec wanted_spec, spec;    char filePath[] = "./src/a.mp4";    // Register all formats and codecs    av_register_all();    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());        exit(1);    }    // Open video file    if (avformat_open_input(&pFormatCtx, filePath, NULL, NULL) != 0)        return -1; // Couldn‘t open file    // Retrieve stream information    if (avformat_find_stream_info(pFormatCtx, NULL) < 0)        return -1; // Couldn‘t find stream information    // Dump information about file onto standard error    av_dump_format(pFormatCtx, 0, filePath, 0);    // Find the first video stream    videoStream = -1;    audioStream = -1;    for (i = 0; i < pFormatCtx->nb_streams; i++) {        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO                && videoStream < 0) {            videoStream = i;        }        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO                && audioStream < 0) {            audioStream = i;        }    }    if (videoStream == -1)        return -1; // Didn‘t find a video stream    if (audioStream == -1)        return -1;    aCodecCtx = pFormatCtx->streams[audioStream]->codec;    // Set audio settings from codec info    wanted_spec.freq = aCodecCtx->sample_rate;    wanted_spec.format = AUDIO_S16SYS;    wanted_spec.channels = aCodecCtx->channels;    wanted_spec.silence = 0;    wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;    wanted_spec.callback = audio_callback;    wanted_spec.userdata = aCodecCtx;    if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {        fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());        return -1;    }    aCodec = avcodec_find_decoder(aCodecCtx->codec_id);    if (!aCodec) {        fprintf(stderr, "Unsupported codec!\n");        return -1;    }    avcodec_open2(aCodecCtx, aCodec, NULL);    // audio_st = pFormatCtx->streams[index]    packet_queue_init(&audioq);    SDL_PauseAudio(0);    // Get a pointer to the codec context for the video stream    pCodecCtx = pFormatCtx->streams[videoStream]->codec;    // Find the decoder for the video stream    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);    if (pCodec == NULL) {        fprintf(stderr, "Unsupported codec!\n");        return -1; // Codec not found    }    // Open codec    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)        return -1; // Could not open codec    // Allocate video frame    pFrame = avcodec_alloc_frame();    pSwsCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height,            pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,            AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL);    // Make a screen to put our video#ifndef __DARWIN__    screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);#else    screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0);#endif    if (!screen) {        fprintf(stderr, "SDL: could not set video mode - exiting\n");        exit(1);    }    // Allocate a place to put our YUV image on that screen    bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,    SDL_YV12_OVERLAY, screen);    return EXIT_SUCCESS;}

  十四、循环读包,并根据是音频包还是视频包,做相应处理

/* ============================================================================ Name        : VideoDecodeTutorial2_1.c Author      : clarck Version     : Copyright   : Your copyright notice Description : Hello World in C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include "SDL/SDL.h"#include "SDL/SDL_thread.h"#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavutil/pixfmt.h"#include "libswscale/swscale.h"#ifdef __MINGW32__#undef main /* Prevents SDL from overriding main() */#endif#define SDL_AUDIO_BUFFER_SIZE 1024#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audiotypedef struct PacketQueue {    AVPacketList *first_pkt, *last_pkt;    int nb_packets;    int size;    SDL_mutex *mutex;    SDL_cond *cond;} PacketQueue;PacketQueue audioq;int quit = 0;void packet_queue_init(PacketQueue *q) {    memset(q, 0, sizeof(PacketQueue));    q->mutex = SDL_CreateMutex();    q->cond = SDL_CreateCond();}int packet_queue_put(PacketQueue *q, AVPacket *pkt) {    AVPacketList *pkt1;    if (av_dup_packet(pkt) < 0) {        return -1;    }    pkt1 = av_malloc(sizeof(AVPacketList));    if (!pkt1)        return -1;    pkt1->pkt = *pkt;    pkt1->next = NULL;    SDL_LockMutex(q->mutex);    if (!q->last_pkt)        q->first_pkt = pkt1;    else        q->last_pkt->next = pkt1;    q->last_pkt = pkt1;    q->nb_packets++;    q->size += pkt1->pkt.size;    SDL_CondSignal(q->cond);    SDL_UnlockMutex(q->mutex);    return 0;}static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) {    AVPacketList *pkt1;    int ret;    SDL_LockMutex(q->mutex);    for (;;) {        if (quit) {            ret = -1;            break;        }        pkt1 = q->first_pkt;        if (pkt1) {            q->first_pkt = pkt1->next;            if (!q->first_pkt)                q->last_pkt = NULL;            q->nb_packets--;            q->size -= pkt1->pkt.size;            *pkt = pkt1->pkt;            av_free(pkt1);            ret = 1;            break;        } else if (!block) {            ret = 0;            break;        } else {            SDL_CondWait(q->cond, q->mutex);        }    }    SDL_UnlockMutex(q->mutex);    return ret;}int audio_decode_frame(AVCodecContext *aCodecCtx, uint8_t *audio_buf,        int buf_size) {    static AVPacket pkt;    static uint8_t *audio_pkt_data =http://www.mamicode.com/ NULL;    static int audio_pkt_size = 0;    static AVFrame frame;    int len1, data_size = 0;    for (;;) {        while (audio_pkt_size > 0) {            int got_frame = 0;            len1 = avcodec_decode_audio4(aCodecCtx, &frame, &got_frame, &pkt);            if (len1 < 0) {                /* if error, skip frame */                audio_pkt_size = 0;                break;            }            audio_pkt_data += len1;            audio_pkt_size -= len1;            if (got_frame) {                data_size = frame.linesize[0];                /*                 data_size = av_samples_get_buffer_size(NULL,                 aCodecCtx->channels, frame.nb_samples,                 aCodecCtx->sample_fmt, 1);                 */                memcpy(audio_buf, frame.data[0], data_size);            }            if (data_size <= 0) {                /* No data yet, get more frames */                continue;            }            /* We have data, return it and come back for more later */            return data_size;        }        if (pkt.data)            av_free_packet(&pkt);        if (quit) {            return -1;        }        if (packet_queue_get(&audioq, &pkt, 1) < 0) {            return -1;        }        audio_pkt_data = pkt.data;        audio_pkt_size = pkt.size;    }    return 0;}void audio_callback(void *userdata, Uint8 *stream, int len) {    AVCodecContext *aCodecCtx = (AVCodecContext *) userdata;    int len1, audio_size;    static uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];    static unsigned int audio_buf_size = 0;    static unsigned int audio_buf_index = 0;    while (len > 0) {        if (audio_buf_index >= audio_buf_size) {            /* We have already sent all our data; get more */            audio_size = audio_decode_frame(aCodecCtx, audio_buf,                    sizeof(audio_buf));            if (audio_size < 0) {                /* If error, output silence */                audio_buf_size = 1024; // arbitrary?                memset(audio_buf, 0, audio_buf_size);            } else {                audio_buf_size = audio_size;            }            audio_buf_index = 0;        }        len1 = audio_buf_size - audio_buf_index;        if (len1 > len)            len1 = len;        memcpy(stream, (uint8_t *) audio_buf + audio_buf_index, len1);        len -= len1;        stream += len1;        audio_buf_index += len1;    }}int main(int argc, char* args[]) {    AVFormatContext *pFormatCtx = NULL;    int i, videoStream, audioStream;    AVCodecContext *pCodecCtx;    AVCodec *pCodec;    AVFrame *pFrame;    AVPacket packet;    struct SwsContext * pSwsCtx;    int frameFinished;    AVCodecContext *aCodecCtx;    AVCodec *aCodec;    SDL_Overlay *bmp;    SDL_Surface *screen;    SDL_Rect rect;    SDL_Event event;    SDL_AudioSpec wanted_spec, spec;    char filePath[] = "./src/a.mp4";    // Register all formats and codecs    av_register_all();    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());        exit(1);    }    // Open video file    if (avformat_open_input(&pFormatCtx, filePath, NULL, NULL) != 0)        return -1; // Couldn‘t open file    // Retrieve stream information    if (avformat_find_stream_info(pFormatCtx, NULL) < 0)        return -1; // Couldn‘t find stream information    // Dump information about file onto standard error    av_dump_format(pFormatCtx, 0, filePath, 0);    // Find the first video stream    videoStream = -1;    audioStream = -1;    for (i = 0; i < pFormatCtx->nb_streams; i++) {        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO                && videoStream < 0) {            videoStream = i;        }        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO                && audioStream < 0) {            audioStream = i;        }    }    if (videoStream == -1)        return -1; // Didn‘t find a video stream    if (audioStream == -1)        return -1;    aCodecCtx = pFormatCtx->streams[audioStream]->codec;    // Set audio settings from codec info    wanted_spec.freq = aCodecCtx->sample_rate;    wanted_spec.format = AUDIO_S16SYS;    wanted_spec.channels = aCodecCtx->channels;    wanted_spec.silence = 0;    wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;    wanted_spec.callback = audio_callback;    wanted_spec.userdata = aCodecCtx;    if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {        fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());        return -1;    }    aCodec = avcodec_find_decoder(aCodecCtx->codec_id);    if (!aCodec) {        fprintf(stderr, "Unsupported codec!\n");        return -1;    }    avcodec_open2(aCodecCtx, aCodec, NULL);    // audio_st = pFormatCtx->streams[index]    packet_queue_init(&audioq);    SDL_PauseAudio(0);    // Get a pointer to the codec context for the video stream    pCodecCtx = pFormatCtx->streams[videoStream]->codec;    // Find the decoder for the video stream    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);    if (pCodec == NULL) {        fprintf(stderr, "Unsupported codec!\n");        return -1; // Codec not found    }    // Open codec    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)        return -1; // Could not open codec    // Allocate video frame    pFrame = avcodec_alloc_frame();    pSwsCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height,            pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,            AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL);    // Make a screen to put our video#ifndef __DARWIN__    screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);#else    screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0);#endif    if (!screen) {        fprintf(stderr, "SDL: could not set video mode - exiting\n");        exit(1);    }    // Allocate a place to put our YUV image on that screen    bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,    SDL_YV12_OVERLAY, screen);    // Read frames and save first five frames to disk    i = 0;    while (av_read_frame(pFormatCtx, &packet) >= 0) {        // Is this a packet from the video stream?        if (packet.stream_index == videoStream) {            // Decode video frame            avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);            // Did we get a video frame?            if (frameFinished) {                SDL_LockYUVOverlay(bmp);                AVPicture pict;                pict.data[0] = bmp->pixels[0];                pict.data[1] = bmp->pixels[2];                pict.data[2] = bmp->pixels[1];                pict.linesize[0] = bmp->pitches[0];                pict.linesize[1] = bmp->pitches[2];                pict.linesize[2] = bmp->pitches[1];                // Convert the image into YUV format that SDL uses                sws_scale(pSwsCtx, (const uint8_t * const *) pFrame->data,                        pFrame->linesize, 0, pCodecCtx->height, pict.data,                        pict.linesize);                SDL_UnlockYUVOverlay(bmp);                rect.x = 0;                rect.y = 0;                rect.w = pCodecCtx->width;                rect.h = pCodecCtx->height;                SDL_DisplayYUVOverlay(bmp, &rect);                av_free_packet(&packet);            }        } else if (packet.stream_index == audioStream) {            packet_queue_put(&audioq, &packet);        } else {            av_free_packet(&packet);        }        // Free the packet that was allocated by av_read_frame        SDL_PollEvent(&event);        switch (event.type) {        case SDL_QUIT:            quit = 1;            SDL_Quit();            exit(0);            break;        default:            break;        }    }    // Free the YUV frame    av_free(pFrame);    // Close the codec    avcodec_close(pCodecCtx);    // Close the video file    avformat_close_input(&pFormatCtx);    return EXIT_SUCCESS;}