如何在Android用FFmpeg+SDL2.0解码声音

如题所述

一、创建一个VideoPicture结构体用来保存解码出来的图像。
  二、添加数据队列的初始化、添加以及读取的函数。
  三、audio_decode_frame():解码音频
  四、audio_callback(): 回调函数,向SDL缓冲区填充数据
  五、创建视频刷新相关的函数:
  schedule_refresh():它主要的作用是告诉系统指定的毫秒数后推FF_REFRESH_EVENT。当我们看到它在事件队列时,将依次调用视频刷新功能。
  六、添加视频显示函数:
  因为我们的屏幕可以是任意大小(我们设定我们为640×480,并有一些方法来设置它,所以它是由用户调整大小),我们需要动态地计算出我们有多大的矩形。因此,首先我们需要弄清楚我们的电影的显示比例,这仅仅是宽度除以身高。某些编解码器将有一个奇怪的样本纵横比,这就是一个像素,或样品的宽度/高度。因为在我们的编解码器的上下文中的高度和宽度值以像素为单位测量,实际的宽高比等于宽高比数倍的样品长宽比。一些编解码器将显示0-5的宽高比,这表示每个像素仅仅是大小1x1的。然后,我们扩展了电影,以适应在我们的屏幕上。
  七、分配显示输出内存空间:
  使用队列中,我们有两个指针 - 写入索引和阅读索引。我们还跟踪实际的照片有多少是在缓冲区中。要写入队列中,我们将首先等待我们的缓冲清除,所以我们足够的空间来存储我们VideoPicture。然后我们检查,看看是否已经分配了覆盖在我们的写作索引。如果没有,我们就必须分配一定的空间。如果窗口的大小发生了变化, 我们也要重新分配缓冲区。
  八、解码线程,将解码器,建立音频线,保存重要信息到数据结构中。
  九、编写Main函数用来调用解码线程。
温馨提示:答案为网友推荐,仅供参考
第1个回答  2015-03-06
一、创建一个VideoPicture结构体用来保存解码出来的图像。
  二、添加数据队列的初始化、添加以及读取的函数。
  三、audio_decode_frame():解码音频
  四、audio_callback(): 回调函数,向SDL缓冲区填充数据
  五、创建视频刷新相关的函数:
  schedule_refresh():它主要的作用是告诉系统指定的毫秒数后推FF_REFRESH_EVENT。当我们看到它在事件队列时,将依次调用视频刷新功能。
  六、添加视频显示函数:
  因为我们的屏幕可以是任意大小(我们设定我们为640×480,并有一些方法来设置它,所以它是由用户调整大小),我们需要动态地计算出我们有多大的矩形。因此,首先我们需要弄清楚我们的电影的显示比例,这仅仅是宽度除以身高。某些编解码器将有一个奇怪的样本纵横比,这就是一个像素,或样品的宽度/高度。因为在我们的编解码器的上下文中的高度和宽度值以像素为单位测量,实际的宽高比等于宽高比数倍的样品长宽比。一些编解码器将显示0-5的宽高比,这表示每个像素仅仅是大小1x1的。然后,我们扩展了电影,以适应在我们的屏幕上。
  七、分配显示输出内存空间:
  使用队列中,我们有两个指针 - 写入索引和阅读索引。我们还跟踪实际的照片有多少是在缓冲区中。要写入队列中,我们将首先等待我们的缓冲清除,所以我们足够的空间来存储我们VideoPicture。然后我们检查,看看是否已经分配了覆盖在我们的写作索引。如果没有,我们就必须分配一定的空间。如果窗口的大小发生了变化, 我们也要重新分配缓冲区。
  八、解码线程,将解码器,建立音频线,保存重要信息到数据结构中。
  九、编写Main函数用来调用解码线程。
第2个回答  2015-03-08
创建一个VideoPicture结构体用来保存解码出来的图像。

/*
* SDL_Lesson.c
*
* Created on: Aug 12, 2014
* Author: clarck
*/
#include <jni.h>
#include <android/native_window_jni.h>
#include "SDL.h"
#include "SDL_thread.h"
#include "SDL_events.h"
#include "../include/logger.h"
#include "../ffmpeg/include/libavcodec/avcodec.h"
#include "../ffmpeg/include/libavformat/avformat.h"
#include "../ffmpeg/include/libavutil/pixfmt.h"
#include "../ffmpeg/include/libswscale/swscale.h"
#include "../ffmpeg/include/libswresample/swresample.h"

#define SDL_AUDIO_BUFFER_SIZE 1024

#define MAX_AUDIO_SIZE (5 * 16 * 1024)
#define MAX_VIDEO_SIZE (5 * 256 * 1024)

#define FF_ALLOC_EVENT (SDL_USEREVENT)
#define FF_REFRESH_EVENT (SDL_USEREVENT + 1)
#define FF_QUIT_EVENT (SDL_USEREVENT + 2)

#define VIDEO_PICTURE_QUEUE_SIZE 1
#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio

typedef struct PacketQueue {
AVPacketList *first_pkt, *last_pkt;
int nb_packets;
int size;
SDL_mutex *mutex;
SDL_cond *cond;
} PacketQueue;

typedef struct VideoPicture {
SDL_Window *screen;
SDL_Renderer *renderer;
SDL_Texture *bmp;

AVFrame* rawdata;
int width, height; /*source height & width*/
int allocated;
} VideoPicture;

typedef struct VideoState {
char filename[1024];
AVFormatContext *ic;
int videoStream, audioStream;
AVStream *audio_st;
AVFrame *audio_frame;
PacketQueue audioq;
unsigned int audio_buf_size;
unsigned int audio_buf_index;
AVPacket audio_pkt;
uint8_t *audio_pkt_data;
int audio_pkt_size;
uint8_t *audio_buf;
DECLARE_ALIGNED(16,uint8_t,audio_buf2) [AVCODEC_MAX_AUDIO_FRAME_SIZE * 4];
enum AVSampleFormat audio_src_fmt;
enum AVSampleFormat audio_tgt_fmt;
int audio_src_channels;
int audio_tgt_channels;
int64_t audio_src_channel_layout;
int64_t audio_tgt_channel_layout;
int audio_src_freq;
int audio_tgt_freq;
struct SwrContext *swr_ctx;

AVStream *video_st;
PacketQueue videoq;

VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
int pictq_size, pictq_rindex, pictq_windex;
SDL_mutex *pictq_mutex;
SDL_cond *pictq_cond;

SDL_Thread *parse_tid;
SDL_Thread *audio_tid;
SDL_Thread *video_tid;

AVIOContext *io_ctx;
struct SwsContext *sws_ctx;

int quit;
} VideoState;

VideoState *global_video_state;

如果我的回答没能帮助您,请继续追问。

转载,仅供参考。本回答被提问者和网友采纳