一、视频编码
#include
using namespace std;
extern "C" {
#include
#include
#include
}
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avutil.lib")
static int encode(AVCodecContext* ctx, AVFrame* frame, AVPacket* pkt, FILE* out) {
int ret = -1;
ret = avcodec_send_frame(ctx, frame);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to send frame to encoder!\n");
goto _END;
}
while (ret >= 0) {
ret = avcodec_receive_packet(ctx, pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
return 0;
}
else if (ret < 0) {
return -1; //退出tkyc
}
fwrite(pkt->data, 1, pkt->size, out);
av_packet_unref(pkt);
}
_END:
return 0;
}
int main(int argc, char* argv[]) {
int ret = -1;
FILE* f = NULL;
const AVCodec* codec = NULL;
AVCodecContext* ctx = NULL;
AVFrame* frame = NULL;
AVPacket* pkt = NULL;
av_log_set_level(AV_LOG_DEBUG);
//1. 输入参数
char dst[] = "1.h264";
char codecName[] = "libx264";
//2. 查找编码器
codec = avcodec_find_encoder_by_name(codecName);
if (!codec) {
av_log(NULL, AV_LOG_ERROR, "don't find Codec: %s", codecName);
goto _ERROR;
}
//3. 创建编码器上下文
ctx = avcodec_alloc_context3(codec);
if (!ctx) {
av_log(NULL, AV_LOG_ERROR, "NO MEMRORY\n");
goto _ERROR;
}
//4. 设置编码器参数
ctx->width = 640;
ctx->height = 480;
ctx->bit_rate = 500000;
//ctx->time_base = (AVRational){ 1, 25 };
ctx->time_base = { 1, 25 };
ctx->framerate = { 25, 1 };
ctx->gop_size = 10;
ctx->max_b_frames = 1;
ctx->pix_fmt = AV_PIX_FMT_YUV420P;
if (codec->id == AV_CODEC_ID_H264) {
av_opt_set(ctx->priv_data, "preset", "slow", 0);
}
//5. 编码器与编码器上下文绑定到一起
ret = avcodec_open2(ctx, codec, NULL);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Don't open codec: %s \n", av_err2str(ret));
goto _ERROR;
}
//6. 创建输出文件
f = fopen(dst, "wb");
if (!f) {
av_log(NULL, AV_LOG_ERROR, "Don't open file:%s", dst);
goto _ERROR;
}
//7. 创建AVFrame
frame = av_frame_alloc();
if (!frame) {
av_log(NULL, AV_LOG_ERROR, "NO MEMORY!\n");
goto _ERROR;
}
frame->width = ctx->width;
frame->height = ctx->height;
frame->format = ctx->pix_fmt;
ret = av_frame_get_buffer(frame, 0);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Could not allocate the video frame \n");
goto _ERROR;
}
//8. 创建AVPacket
pkt = av_packet_alloc();
if (!pkt) {
av_log(NULL, AV_LOG_ERROR, "NO MEMORY!\n");
goto _ERROR;
}
//9. 生成视频内容
for (int i = 0; i < 25; i++) {
ret = av_frame_make_writable(frame);
if (ret < 0) {
break;
}
//Y分量
for (int y = 0; y < ctx->height; y++) {
for (int x = 0; x < ctx->width; x++) {
frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
}
}
//UV分量
for (int y = 0; y < ctx->height / 2; y++) {
for (int x = 0; x < ctx->width / 2; x++) {
frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;
frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;
}
}
frame->pts = i;
//10. 编码
ret = encode(ctx, frame, pkt, f);
if (ret == -1) {
goto _ERROR;
}
}
//10. 编码
encode(ctx, NULL, pkt, f);
_ERROR:
//ctx
if (ctx) {
avcodec_free_context(&ctx);
}
//avframe
if (frame) {
av_frame_free(&frame);
}
//avpacket
if (pkt) {
av_packet_free(&pkt);
}
//dst
if (f) {
fclose(f);
}
return 0;
}
二、音频编码
#include
using namespace std;
extern "C" {
#include
#include
#include
#include
#include
}
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"avformat.lib")
static int select_best_sample_rate(const AVCodec* codec) {
const int* p;
int best_samplerate = 0;
if (!codec->supported_samplerates) {
return 44100;
}
p = codec->supported_samplerates;
while (*p) {
if (!best_samplerate || abs(44100 - *p) < abs(44100 - best_samplerate)) {
best_samplerate = *p;
}
p++;
}
return best_samplerate;
}
static int check_sample_fmt(const AVCodec* codec, enum AVSampleFormat sample_fmt) {
const enum AVSampleFormat* p = codec->sample_fmts;
while (*p != AV_SAMPLE_FMT_NONE) {
if (*p == sample_fmt) {
return 1;
}
p++;
}
return 0;
}
static int encode(AVCodecContext* ctx, AVFrame* frame, AVPacket* pkt, FILE* out) {
int ret = -1;
ret = avcodec_send_frame(ctx, frame);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to send frame to encoder: %s!\n", av_err2str(ret));
goto _END;
}
while (ret >= 0) {
ret = avcodec_receive_packet(ctx, pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
return 0;
}
else if (ret < 0) {
return -1; //退出tkyc
}
av_log(NULL, AV_LOG_DEBUG, "ptk.size:%d\n", pkt->size);
fwrite(pkt->data, 1, pkt->size, out);
av_packet_unref(pkt);
}
_END:
return 0;
}
int main(int argc, char* argv[]) {
int ret = -1;
FILE* f = NULL;
char* dst = NULL;
char* codecName = NULL;
const AVCodec* codec = NULL;
AVCodecContext* ctx = NULL;
AVFrame* frame = NULL;
AVPacket* pkt = NULL;
uint16_t* samples = NULL;
av_log_set_level(AV_LOG_DEBUG);
//1. 输入参数
if (argc < 2) {
av_log(NULL, AV_LOG_ERROR, "arguments must be more than 2\n");
goto _END;
}
dst = argv[1];
//codecName = argv[2];
//2. 查找编码器
//codec = avcodec_find_encoder_by_name(codecName);
codec = avcodec_find_encoder_by_name("libfdk_aac");
//codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
if (!codec) {
av_log(NULL, AV_LOG_ERROR, "don't find Codec: %s", codecName);
goto _END;
}
//3. 创建编码器上下文
ctx = avcodec_alloc_context3(codec);
if (!ctx) {
av_log(NULL, AV_LOG_ERROR, "NO MEMRORY\n");
goto _END;
}
//4. 设置编码器参数
ctx->bit_rate = 64000;
ctx->sample_fmt = AV_SAMPLE_FMT_S16;//AV_SAMPLE_FMT_FLTP
if (!check_sample_fmt(codec, ctx->sample_fmt)) {
av_log(NULL, AV_LOG_ERROR, "Encoder does not support sample format!\n");
goto _END;
}
ctx->sample_rate = select_best_sample_rate(codec);
av_channel_layout_copy(&ctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO); //AV_CHANNEL_LAYOUT_MONO
//5. 编码器与编码器上下文绑定到一起
ret = avcodec_open2(ctx, codec, NULL);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Don't open codec: %s \n", av_err2str(ret));
goto _END;
}
//6. 创建输出文件
f = fopen(dst, "wb");
if (!f) {
av_log(NULL, AV_LOG_ERROR, "Don't open file:%s", dst);
goto _END;
}
//7. 创建AVFrame
frame = av_frame_alloc();
if (!frame) {
av_log(NULL, AV_LOG_ERROR, "NO MEMORY!\n");
goto _END;
}
frame->nb_samples = ctx->frame_size;
frame->format = AV_SAMPLE_FMT_S16; //AV_SAMPLE_FMT_FLTP
av_channel_layout_copy(&frame->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO); //AV_CHANNEL_LAYOUT_MONO
frame->sample_rate = ctx->sample_rate;
ret = av_frame_get_buffer(frame, 0);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Could not allocate the video frame \n");
goto _END;
}
//8. 创建AVPacket
pkt = av_packet_alloc();
if (!pkt) {
av_log(NULL, AV_LOG_ERROR, "NO MEMORY!\n");
goto _END;
}
//9. 生成音频内容
float t = 0;
float tincr = 4 * M_PI * 440 / ctx->sample_rate;
for (int i = 0; i < 200; i++) {
ret = av_frame_make_writable(frame);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Could not allocate space!\n");
goto _END;
}
samples = (uint16_t*)frame->data[0]; //FLTP 32 (uint32_t*)
for (int j = 0; j < ctx->frame_size; j++) {
samples[2 * j] = (int)(sin(t) * 10000); //4
for (int k = 1; k < ctx->ch_layout.nb_channels; k++) {
samples[2 * j + k] = samples[2 * j]; //4
}
t += tincr;
}
encode(ctx, frame, pkt, f);
}
//10. 编码
encode(ctx, NULL, pkt, f);
_END:
//ctx
if (ctx) {
avcodec_free_context(&ctx);
}
//avframe
if (frame) {
av_frame_free(&frame);
}
//avpacket
if (pkt) {
av_packet_free(&pkt);
}
//dst
if (f) {
fclose(f);
}
return 0;
}
三、生成图片
extern "C" {
#include
#include
#include
#include
#include
#include
#include
}
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"swscale.lib")
#define WORD uint16_t
#define DWORD uint32_t
#define LONG int32_t
#pragma pack(2)
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER, * LPBITMAPFILEHEADER, * PBITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER, * LPBITMAPINFOHEADER, * PBITMAPINFOHEADER;
static void saveBMP(struct SwsContext* swsCtx,
AVFrame* frame,
int w,
int h,
char* name) {
FILE* f = NULL;
int dataSize = w * h * 3;
//1. 先进行转换,将YUV frame 转成 BGR24 Frame
AVFrame* frameBGR = av_frame_alloc();
frameBGR->width = w;
frameBGR->height = h;
frameBGR->format = AV_PIX_FMT_BGR24;
av_frame_get_buffer(frameBGR, 0);
sws_scale(swsCtx,
(const uint8_t* const*)frame->data,
frame->linesize,
0,
frame->height,
frameBGR->data,
frameBGR->linesize);
//2. 构造 BITMAPINFOHEADER
BITMAPINFOHEADER infoHeader;
infoHeader.biSize = sizeof(BITMAPINFOHEADER);
infoHeader.biWidth = w;
infoHeader.biHeight = h * (-1);
infoHeader.biBitCount = 24;
infoHeader.biCompression = 0;
infoHeader.biSizeImage = 0;
infoHeader.biClrImportant = 0;
infoHeader.biClrUsed = 0;
infoHeader.biXPelsPerMeter = 0;
infoHeader.biYPelsPerMeter = 0;
infoHeader.biPlanes = 1;
//3. 构造 BITMAPFILEHEADER
BITMAPFILEHEADER fileHeader = { 0, };
fileHeader.bfType = 0x4d42; //'BM'
fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dataSize;
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
//4. 将数据写到文件
f = fopen(name, "wb");
fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, f);
fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, f);
fwrite(frameBGR->data[0], 1, dataSize, f);
//5. 释放资源
fclose(f);
av_freep(&frameBGR->data[0]);
av_free(frameBGR);
}
static void savePic(unsigned char* buf, int linesize, int width, int height, char* name) {
FILE* f;
f = fopen(name, "wb");
fprintf(f, "P5\n%d %d\n%d\n", width, height, 255);
for (int i = 0; i < height; i++) {
fwrite(buf + i * linesize, 1, width, f);
}
fclose(f);
}
static int decode(AVCodecContext* ctx,
struct SwsContext* swsCtx,
AVFrame* frame, AVPacket* pkt,
const char* fileName) {
int ret = -1;
char buf[1024];
ret = avcodec_send_packet(ctx, pkt);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to send frame to decoder!\n");
goto _END;
}
while (ret >= 0) {
ret = avcodec_receive_frame(ctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
return 0;
}
else if (ret < 0) {
return -1; //退出程序
}
snprintf(buf, sizeof(buf), "%s-%d.bmp", fileName, ctx->frame_number);
saveBMP(swsCtx, frame, 640, 360, buf);
/*
savePic(frame->data[0],
frame->linesize[0],
frame->width,
frame->height,
buf);*/
if (pkt) {
av_packet_unref(pkt);
}
}
_END:
return 0;
}
int main(int argc, char* argv[]) {
int ret = -1;
int idx = -1;
//1. 处理一些参数;
const char* src = "1.mp4";
const char* dst = "111";
const AVCodec* codec = NULL;
AVCodecContext* ctx = NULL;
AVFormatContext* pFmtCtx = NULL;
AVStream* inStream = NULL;
AVFrame* frame = NULL;
AVPacket* pkt = NULL;
struct SwsContext* swsCtx = NULL;
av_log_set_level(AV_LOG_DEBUG);
//2. 打开多媒体文件
if ((ret = avformat_open_input(&pFmtCtx, src, NULL, NULL)) < 0) {
av_log(NULL, AV_LOG_ERROR, "%s\n", av_err2str(ret));
exit(-1);
}
//3. 从多媒体文件中找到视频流
idx = av_find_best_stream(pFmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
if (idx < 0) {
av_log(pFmtCtx, AV_LOG_ERROR, "Does not include audio stream!\n");
goto _ERROR;
}
inStream = pFmtCtx->streams[idx];
//4. 查找解码器
codec = avcodec_find_decoder(inStream->codecpar->codec_id);
if (!codec) {
av_log(NULL, AV_LOG_ERROR, "Could not find libx264 Codec");
goto _ERROR;
}
//5. 创建解码器上下文
ctx = avcodec_alloc_context3(NULL);
if (!ctx) {
av_log(NULL, AV_LOG_ERROR, "NO MEMRORY\n");
goto _ERROR;
}
ret = avcodec_parameters_to_context(ctx, inStream->codecpar);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Could not copyt codecpar to codec ctx!\n");
goto _ERROR;
}
//5. 解码器与解码器上下文绑定到一起
ret = avcodec_open2(ctx, codec, NULL);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Don't open codec: %s \n", av_err2str(ret));
goto _ERROR;
}
//5.1 获得SWS上下文
swsCtx = sws_getContext(ctx->width, //src width
ctx->height, //src height
AV_PIX_FMT_YUV420P,//src pix fmt
640, //dst width
360, //dst height
AV_PIX_FMT_BGR24, //dst pix fmt
SWS_BICUBIC, NULL, NULL, NULL);
if (!swsCtx) {
av_log(NULL, AV_LOG_ERROR, "Could not get Swscale Context!\n");
goto _ERROR;
}
//6. 创建AVFrame
frame = av_frame_alloc();
if (!frame) {
av_log(NULL, AV_LOG_ERROR, "NO MEMORY!\n");
goto _ERROR;
}
//7. 创建AVPacket
pkt = av_packet_alloc();
if (!pkt) {
av_log(NULL, AV_LOG_ERROR, "NO MEMORY!\n");
goto _ERROR;
}
//8. 从源多媒体文件中读到视频数据
while (av_read_frame(pFmtCtx, pkt) >= 0) {
if (pkt->stream_index == idx) {
decode(ctx, swsCtx, frame, pkt, dst);
}
}
decode(ctx, swsCtx, frame, NULL, dst);
//9. 将申请的资源释放掉
_ERROR:
if (pFmtCtx) {
avformat_close_input(&pFmtCtx);
pFmtCtx = NULL;
}
if (ctx) {
avcodec_free_context(&ctx);
ctx = NULL;
}
if (frame) {
av_frame_free(&frame);
frame = NULL;
}
if (pkt) {
av_packet_free(&pkt);
pkt = NULL;
}
if (swsCtx) {
sws_freeContext(swsCtx);
swsCtx = NULL;
}
printf("hello, world!\n");
return 0;
}
四、生成彩色BMP图片
extern "C" {
#include
#include
#include
#include
#include
#include
}
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"swscale.lib")
#define WORD uint16_t
#define DWORD uint32_t
#define LONG int32_t
#pragma pack(2)
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER, * PBITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER, * PBITMAPINFOHEADER;
void saveBMP(struct SwsContext* img_convert_ctx, AVFrame* frame, int w, int h, char* filename)
{
//1 先进行转换, YUV420=>RGB24:
// int w = img_convert_ctx->frame_dst->width;
// int h = img_convert_ctx->frame_dst->height;
int data_size = w * h * 3;
AVFrame* pFrameRGB = av_frame_alloc();
//avpicture_fill((AVPicture *)pFrameRGB, buffer, AV_PIX_FMT_BGR24, w, h);
pFrameRGB->width = w;
pFrameRGB->height = h;
pFrameRGB->format = AV_PIX_FMT_BGR24;
av_frame_get_buffer(pFrameRGB, 0);
sws_scale(img_convert_ctx,
(const uint8_t* const*)frame->data,
frame->linesize,
0, frame->height, pFrameRGB->data, pFrameRGB->linesize);
//2 构造 BITMAPINFOHEADER
BITMAPINFOHEADER header;
header.biSize = sizeof(BITMAPINFOHEADER);
header.biWidth = w;
header.biHeight = h * (-1);
header.biBitCount = 24;
header.biCompression = 0;
header.biSizeImage = 0;
header.biClrImportant = 0;
header.biClrUsed = 0;
header.biXPelsPerMeter = 0;
header.biYPelsPerMeter = 0;
header.biPlanes = 1;
//3 构造文件头
BITMAPFILEHEADER bmpFileHeader = { 0, };
//HANDLE hFile = NULL;
DWORD dwTotalWriten = 0;
DWORD dwWriten;
bmpFileHeader.bfType = 0x4d42; //'BM';
bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + data_size;
bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
FILE* pf = fopen(filename, "wb");
fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, pf);
fwrite(&header, sizeof(BITMAPINFOHEADER), 1, pf);
fwrite(pFrameRGB->data[0], 1, data_size, pf);
fclose(pf);
//释放资源
//av_free(buffer);
av_freep(&pFrameRGB[0]);
av_free(pFrameRGB);
}
static void pgm_save(unsigned char* buf, int wrap, int xsize, int ysize,
char* filename)
{
FILE* f;
int i;
f = fopen(filename, "w");
fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
for (i = 0; i < ysize; i++)
fwrite(buf + i * wrap, 1, xsize, f);
fclose(f);
}
static int decode_write_frame(const char* outfilename, AVCodecContext* avctx,
struct SwsContext* img_convert_ctx, AVFrame* frame, AVPacket* pkt)
{
int ret = -1;
char buf[1024];
ret = avcodec_send_packet(avctx, pkt);
if (ret < 0) {
fprintf(stderr, "Error while decoding frame, %s(%d)\n", av_err2str(ret), ret);
return ret;
}
while (ret >= 0) {
fflush(stdout);
ret = avcodec_receive_frame(avctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
return 0;
}
else if (ret < 0) {
return -1;
}
/* the picture is allocated by the decoder, no need to free it */
snprintf(buf, sizeof(buf), "%s-%d.bmp", outfilename, avctx->frame_number);
/*pgm_save(frame->data[0], frame->linesize[0],
frame->width, frame->height, buf);*/
saveBMP(img_convert_ctx, frame, 160, 120, buf);
}
return 0;
}
int main(int argc, char** argv)
{
int ret;
int idx;
const char* filename = "1.mp4";
const char* outfilename = "111";
AVFormatContext* fmt_ctx = NULL;
const AVCodec* codec = NULL;
AVCodecContext* ctx = NULL;
AVStream* inStream = NULL;
AVFrame* frame = NULL;
AVPacket avpkt;
struct SwsContext* img_convert_ctx;
/* open input file, and allocate format context */
if (avformat_open_input(&fmt_ctx, filename, NULL, NULL) < 0) {
fprintf(stderr, "Could not open source file %s\n", filename);
exit(1);
}
/* retrieve stream information */
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
fprintf(stderr, "Could not find stream information\n");
exit(1);
}
/* dump input information to stderr */
//av_dump_format(fmt_ctx, 0, filename, 0);
//av_init_packet(&avpkt);
/* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */
//memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE);
//
idx = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
if (idx < 0) {
fprintf(stderr, "Could not find %s stream in input file '%s'\n",
av_get_media_type_string(AVMEDIA_TYPE_VIDEO), filename);
return idx;
}
inStream = fmt_ctx->streams[idx];
/* find decoder for the stream */
codec = avcodec_find_decoder(inStream->codecpar->codec_id);
if (!codec) {
fprintf(stderr, "Failed to find %s codec\n",
av_get_media_type_string(AVMEDIA_TYPE_VIDEO));
return AVERROR(EINVAL);
}
ctx = avcodec_alloc_context3(NULL);
if (!ctx) {
fprintf(stderr, "Could not allocate video codec context\n");
exit(1);
}
/* Copy codec parameters from input stream to output codec context */
if ((ret = avcodec_parameters_to_context(ctx, inStream->codecpar)) < 0) {
fprintf(stderr, "Failed to copy %s codec parameters to decoder context\n",
av_get_media_type_string(AVMEDIA_TYPE_VIDEO));
return ret;
}
/* open it */
if (avcodec_open2(ctx, codec, NULL) < 0) {
fprintf(stderr, "Could not open codec\n");
exit(1);
}
img_convert_ctx = sws_getContext(ctx->width, ctx->height,
ctx->pix_fmt,
160, 120,
AV_PIX_FMT_BGR24,
SWS_BICUBIC, NULL, NULL, NULL);
if (img_convert_ctx == NULL)
{
fprintf(stderr, "Cannot initialize the conversion context\n");
exit(1);
}
frame = av_frame_alloc();
if (!frame) {
fprintf(stderr, "Could not allocate video frame\n");
exit(1);
}
while (av_read_frame(fmt_ctx, &avpkt) >= 0) {
if (avpkt.stream_index == idx) {
if (decode_write_frame(outfilename, ctx, img_convert_ctx, frame, &avpkt) < 0)
exit(1);
}
av_packet_unref(&avpkt);
}
decode_write_frame(outfilename, ctx, img_convert_ctx, frame, NULL);
avformat_close_input(&fmt_ctx);
sws_freeContext(img_convert_ctx);
avcodec_free_context(&ctx);
av_frame_free(&frame);
return 0;
}