#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>
#include <sys/mman.h>
#include <assert.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avio.h>
#include <libavutil/file.h>
#include <libavutil/pixdesc.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
int file;
int saveAsJPEG(AVFrame *pFrame, int index) {
fprintf(stdout, "ok 0 \n");
int width = pFrame->width;
int height = pFrame->height;
AVCodecContext *pCodeCtx = NULL;
char out_name[32];
sprintf(out_name, "frame%d.png", index);
fprintf(stdout, "out_name: %d \n", index);
AVFormatContext *output_format_context = NULL;
avformat_alloc_output_context2(&output_format_context, NULL, NULL,
out_name);
fprintf(stdout, "mime_type %s \n",
output_format_context->oformat->mime_type);
// 构建一个新stream
AVStream *pAVStream = avformat_new_stream(output_format_context, 0);
if (pAVStream == NULL) {
return -1;
}
AVCodecParameters *parameters = pAVStream->codecpar;
parameters->codec_id = output_format_context->oformat->video_codec;
parameters->codec_type = AVMEDIA_TYPE_VIDEO;
parameters->format = AV_PIX_FMT_YUVJ420P;
parameters->width = pFrame->width;
parameters->height = pFrame->height;
AVCodec *pCodec = avcodec_find_encoder(pAVStream->codecpar->codec_id);
pCodeCtx = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(pCodeCtx, pAVStream->codecpar);
pCodeCtx->time_base = (AVRational ) { 1, 25 };
avcodec_open2(pCodeCtx, pCodec, NULL);
avformat_write_header(output_format_context, NULL);
int y_size = width * height;
AVPacket pkt;
av_new_packet(&pkt, y_size * 10);
printf("av_new_packet %d \n", index);
int ret = avcodec_send_frame(pCodeCtx, pFrame);
if (ret < 0) {
perror("avcodec_send_frame");
return -1;
}
ret = avcodec_receive_packet(pCodeCtx, &pkt);
if (ret < 0) {
perror("avcodec_receive_packet");
return -1;
}
printf("start write packet to file\n");
printf("pkt.size = %d\n", pkt.size); // 62448
if (write(file, pkt.data, pkt.size) < 0)
perror("write");
else
printf("write success \n");
ret = av_write_frame(output_format_context, &pkt);
if (ret < 0) {
printf("Could not av_write_frame");
return -1;
}
av_packet_unref(&pkt);
//Write Trailer
av_write_trailer(output_format_context);
avcodec_close(pCodeCtx);
avio_close(output_format_context->pb);
avformat_free_context(output_format_context);
// av_packet_free(&pkt);
return 0;
}
/**
* 1280*720*12/8 = 1382400 bytes.
* img file size is also 62448 bytes.
*
*/
int main(int argc, char **argv) {
int ret;
file = open("output.yuv", O_WRONLY | O_CREAT | O_TRUNC);
const char *inFileName = "../missu.mp4";
AVFormatContext *ifmt_ctx = NULL;
AVPacket *packet = NULL;
packet = av_packet_alloc();
AVFrame *pFrame = NULL;
AVCodecContext *decode_ctx;
pFrame = av_frame_alloc();
if (avformat_open_input(&ifmt_ctx, inFileName, NULL, NULL) != 0) {
perror("avformat_open_input");
return -1;
}
if (avformat_find_stream_info(ifmt_ctx, NULL) < 0) {
perror("avformat_find_stream_info");
fprintf(stdout, "Couldn't find stream information \n");
return -1;
}
// av_dump_format(ifmt_ctx, 0, NULL, 0);
printf("streams number : %d \n", ifmt_ctx->nb_streams);
if (ifmt_ctx->nb_streams == 0) {
printf("nb_streams is 0,exit \n");
return -1;
}
// Find the first video stream
int videoStream = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1,
NULL, 0);
if (videoStream == -1) {
printf("Didn't find a video stream \n");
return -1;
}
AVStream *stream = ifmt_ctx->streams[videoStream];
// Copy contexts
const AVCodec *decoder = avcodec_find_decoder(stream->codecpar->codec_id);
printf("decoder->name = %s \n", decoder->name); // h264
printf("decoder->long_name = %s \n", decoder->long_name);
printf("decoder->type = %s \n", decoder->type);
// printf("decoder->type = %d \n",decoder->pix_fmts[0]);
printf("decoder->AVCodecID = %d \n", decoder->id); //AV_CODEC_ID_H264
decode_ctx = avcodec_alloc_context3(decoder);
if (!decode_ctx) {
fprintf(stderr, "Could not allocate video codec context\n");
exit(1);
}
ret = avcodec_parameters_to_context(decode_ctx, stream->codecpar);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR,
"Failed to copy decoder parameters to input decoder context "
"for stream\n");
return ret;
}
ret = avcodec_open2(decode_ctx, decoder, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream \n");
return ret;
}
int i = 0;
while (av_read_frame(ifmt_ctx, packet) >= 0) {
if (packet->stream_index == videoStream) {
i++;
dd: ret = avcodec_send_packet(decode_ctx, packet);
if (ret < 0) {
if (ret == AVERROR(EAGAIN)) {
av_log(NULL, AV_LOG_ERROR, "AVERROR(EAGAIN) \n");
}
av_log(NULL, AV_LOG_ERROR, "Decoding failed: %d \n", ret);
break;
}
ret = avcodec_receive_frame(decode_ctx, pFrame);
if (ret == AVERROR(EAGAIN)) {
goto dd;
}
if (ret != 0) {
av_log(NULL, AV_LOG_ERROR,
"avcodec_receive_frame: failed %d \n", ret);
break;
}
if (ret == 0) {
fprintf(stdout, "we get a video frame \n");
saveAsJPEG(pFrame, i);
}
}
}
end: av_frame_free(&pFrame);
av_packet_free(&packet);
avformat_close_input(&ifmt_ctx);
return 0;
}
标签:include,ffmpeg,decoder,ctx,jpg,MP4,ret,av,NULL
From: https://www.cnblogs.com/lidabo/p/17648766.html