Ticket #7290: av.c

File av.c, 3.5 KB (added by lpz, 8 years ago)
Line 
1//
2// av.c
3// splayer
4//
5// Created by 韩爱东 on 2018/6/25.
6// Copyright © 2018年 韩爱东. All rights reserved.
7//
8
9#include "av.h"
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <pthread.h>
14#include <unistd.h>
15#include "libavcodec/avcodec.h"
16#include "libavformat/avformat.h"
17#include "libswscale/swscale.h"
18
19#define INBUF_SIZE 4096
20AVFrame *frame;
21AVCodecContext *codec_ctx;
22pthread_mutex_t frame_lock = PTHREAD_MUTEX_INITIALIZER;
23#if 1
24static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, char *filename)
25{
26 FILE *f;
27 int i;
28 f = fopen(filename,"w");
29 fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
30 for (i = 0; i < ysize; i++)
31 fwrite(buf + i * wrap, 1, xsize, f);
32 fclose(f);
33}
34#endif
35static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt, const char *filename)
36{
37 char buf[1024] = {0};
38 int ret;
39
40 ret = avcodec_send_packet(dec_ctx, pkt);
41 if (ret < 0)
42 {
43 fprintf(stderr, "Error sending a packet for decoding\n");
44 return;
45 }
46
47 while (ret >= 0)
48 {
49 ret = avcodec_receive_frame(dec_ctx, frame);
50 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
51 {
52 printf("err ret = %d.%d, %d\n", ret, AVERROR(EAGAIN), AVERROR_EOF);
53 return;
54 }
55 else if (ret < 0)
56 {
57 fprintf(stderr, "Error during decoding\n");
58 return;
59 }
60 //printf("saving frame %3d\n", dec_ctx->frame_number);
61 fflush(stdout);
62 /* the picture is allocated by the decoder. no need to
63 free it */
64 snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number);
65 pgm_save(frame->data[0], frame->linesize[0], frame->width, frame->height, buf);
66 }
67}
68
69void decode_file(int t)
70{
71 char *filename = "/Users/lpz/splayer/splayer/splayer/ii.mp4";
72 char *outfilename = "/Users/lpz/splayer/splayer/splayer/test/ee";
73 AVPacket *pkt = NULL;
74 AVCodec *codec = NULL;
75 AVStream *stream = NULL;
76 AVFormatContext *fmt_ctx = NULL;
77
78 int i = 0;
79 int videoStream = 0;
80
81 avformat_open_input(&fmt_ctx, filename, NULL, NULL);//打开一个视频
82 avformat_find_stream_info(fmt_ctx, NULL);//读取视频,然后得到流和码率等信息
83 av_dump_format(fmt_ctx, 0, filename, 0);
84 for(i = 0; i < fmt_ctx->nb_streams; ++i)
85 {
86 stream = fmt_ctx->streams[i];
87 if(fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
88 {
89 videoStream=i;
90
91 break;
92 }
93 }
94 printf("videoStream = %d\n", videoStream);
95
96 codec = avcodec_find_decoder(stream->codecpar->codec_id);
97 codec_ctx = avcodec_alloc_context3(codec);//需要使用avcodec_free_context释放
98
99 //事实上codecpar包含了大部分解码器相关的信息,这里是直接从AVCodecParameters复制到AVCodecContext
100 avcodec_parameters_to_context(codec_ctx, stream->codecpar);
101 avcodec_open2(codec_ctx, codec, NULL);
102
103 pkt = av_packet_alloc();
104 if (!pkt)
105 {
106 return;
107 }
108
109 frame = av_frame_alloc();
110 if (!frame)
111 {
112 fprintf(stderr, "Could not allocate video frame\n");
113 return;
114 }
115 while(av_read_frame(fmt_ctx, pkt) >= 0)
116 {
117 printf("pkt->size = %d. %d\n", pkt->size, pkt->stream_index);
118 if(pkt->stream_index == videoStream && pkt->size > 0)
119 {
120 //pthread_mutex_lock(&frame_lock);
121 decode(codec_ctx, frame, pkt, outfilename);
122 //printf("frame = %#x, %d, %d.\n", frame->data[0], frame->width, frame->height);
123 //pthread_mutex_unlock(&frame_lock);
124 }
125
126 usleep(40000);
127 }
128 /* flush the decoder */
129 avcodec_close(codec_ctx);
130 avcodec_free_context(&codec_ctx);
131 av_frame_free(&frame);
132 av_packet_free(&pkt);
133 return;
134}
135
136int main()
137{
138 pthread_t tid;
139 if(pthread_mutex_init(&frame_lock, NULL) != 0)
140 {
141 return -1;
142 }
143
144 pthread_create(&tid, NULL, (void *)&decode_file, &tid);
145 sleep(100);
146 return 0;
147}