//CVideoPlayer.h
#ifndef CVIDEOPLAYER_H
#define CVIDEOPLAYER_H
#include <QThread>
#include <QImage>
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
#include <libavutil/time.h>
#include "libavutil/pixfmt.h"
#include "libswresample/swresample.h"
#include <SDL.h>
#undef main
}
class CVideoPlayer: public QThread
{
Q_OBJECT
public:
CVideoPlayer();
void videoDecode();
protected:
void run();
signals:
void signalGetOneFrame(QImage image);
void signalDecodeError(int error);
};
#endif // CVIDEOPLAYER_H
//CVideoPlayer.cpp
#include "CVideoPlayer.h"
#include <stdio.h>
#include <QDebug>
typedef struct PacketQueue {
AVPacketList *first_pkt, *last_pkt;
int nb_packets;
int size;
SDL_mutex *mutex;
SDL_cond *cond;
} PacketQueue;
#define VIDEO_PICTURE_QUEUE_SIZE 1
#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio
typedef struct VideoState {
AVCodecContext *aCodecCtx; //音频解码器
AVFrame *audioFrame;// 解码音频过程中的使用缓存
PacketQueue *audioq;
double video_clock; ///<pts of last decoded frame / predicted pts of next decoded frame
AVStream *video_st;
} VideoState;
#define SDL_AUDIO_BUFFER_SIZE 1024
VideoState mVideoState; //用来 传递给 SDL音频回调函数的数据
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 = (AVPacketList*)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;
}
//http://blog.yundiantech.com/?log=blog&id=9
static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) {
AVPacketList *pkt1;
int ret;
SDL_LockMutex(q->mutex);
for (;;) {
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(VideoState *is, uint8_t *audio_buf, int buf_size)
{
static AVPacket pkt;
static uint8_t *audio_pkt_data = NULL;
static int audio_pkt_size = 0;
int len1, data_size;
AVCodecContext *aCodecCtx = is->aCodecCtx;
AVFrame *audioFrame = is->audioFrame;
PacketQueue *audioq = is->audioq;
for(;;)
{
if(packet_queue_get(audioq, &pkt, 1) < 0)
{
return -1;
}
audio_pkt_data = pkt.data;
audio_pkt_size = pkt.size;
while(audio_pkt_size > 0)
{
int got_picture;
int ret = avcodec_decode_audio4( aCodecCtx