1+ /*
2+ * Copyright (c) 2006-2020, RT-Thread Development Team
3+ *
4+ * SPDX-License-Identifier: GPL-2.0
5+ *
6+ * Change Logs:
7+ * Date Author Notes
8+ * 2023-9-14 zbtrs The first version
9+ */
10+
11+
12+ #include <stdio.h>
13+ #include <unistd.h>
14+ #include <libavcodec/avcodec.h>
15+ #include <libavformat/avformat.h>
16+ #include <libswscale/swscale.h>
17+ #include <SDL2/SDL.h>
18+ #include <SDL2/SDL_image.h>
19+
20+ #define rtt_screen_width 480
21+ #define rtt_screen_height 272
22+
23+
24+ int main (int argc , char * argv [])
25+ {
26+ int ret = -1 ;
27+ AVFormatContext * pFormatCtx = NULL ;
28+ int videoStream ;
29+ AVCodecParameters * pCodecParameters = NULL ;
30+ AVCodecContext * pCodecCtx = NULL ;
31+ AVCodec * pCodec = NULL ;
32+ AVFrame * pFrame = NULL ;
33+ AVPacket packet ;
34+
35+
36+ SDL_Rect rect ;
37+ SDL_Window * win = NULL ;
38+ SDL_Renderer * renderer = NULL ;
39+ SDL_Texture * texture = NULL ;
40+
41+ if (( argc != 2 ))
42+ {
43+ printf ("error input arguments!\n" );
44+ return (1 );
45+ }
46+
47+ // 默认窗口大小
48+ int w_width = rtt_screen_width ;
49+ int w_height = rtt_screen_height ;
50+
51+ // use dummy video driver
52+ SDL_setenv ("SDL_VIDEODRIVER" ,"rtt" ,1 );
53+ //Initialize SDL
54+ if ( SDL_Init ( SDL_INIT_VIDEO ) < 0 )
55+ {
56+ printf ( "SDL could not initialize! SDL_Error: %s\n" , SDL_GetError ());
57+ return -1 ;
58+ }
59+
60+ // 打开输入文件
61+ if (avformat_open_input (& pFormatCtx , argv [1 ], NULL , NULL ) != 0 )
62+ {
63+ printf ("Couldn't open video file!: %s\n" , argv [1 ]);
64+ goto __exit ;
65+ }
66+
67+ // 找到视频流
68+ videoStream = av_find_best_stream (pFormatCtx , AVMEDIA_TYPE_VIDEO , -1 , -1 , NULL , 0 );
69+ if (videoStream == -1 )
70+ {
71+ printf ("Din't find a video stream!\n" );
72+ goto __exit ;// Didn't find a video stream
73+ }
74+
75+ // 流参数
76+ pCodecParameters = pFormatCtx -> streams [videoStream ]-> codecpar ;
77+
78+ // 获取解码器
79+ pCodec = avcodec_find_decoder (pCodecParameters -> codec_id );
80+ if (pCodec == NULL )
81+ {
82+ printf ("Unsupported codec!\n" );
83+ goto __exit ; // Codec not found
84+ }
85+
86+ // 初始化一个编解码上下文
87+ pCodecCtx = avcodec_alloc_context3 (pCodec );
88+ if (avcodec_parameters_to_context (pCodecCtx , pCodecParameters ) != 0 )
89+ {
90+ printf ("Couldn't copy codec context\n" );
91+ goto __exit ;// Error copying codec context
92+ }
93+
94+ // 打开解码器
95+ if (avcodec_open2 (pCodecCtx , pCodec , NULL ) < 0 )
96+ {
97+ printf ("Failed to open decoder!\n" );
98+ goto __exit ; // Could not open codec
99+ }
100+
101+ // Allocate video frame
102+ pFrame = av_frame_alloc ();
103+ if (NULL == pFrame ) {
104+ printf ("av_frame_alloc error\n" );
105+ goto __exit ;
106+ }
107+
108+ w_width = pCodecCtx -> width ;
109+ w_height = pCodecCtx -> height ;
110+
111+ // 创建窗口
112+ win = SDL_CreateWindow ("Media Player" ,
113+ SDL_WINDOWPOS_UNDEFINED ,
114+ SDL_WINDOWPOS_UNDEFINED ,
115+ w_width , w_height ,
116+ SDL_WINDOW_SHOWN );
117+ if (!win )
118+ {
119+ printf ("Failed to create window by SDL\n" );
120+ goto __exit ;
121+ }
122+
123+ // 创建渲染器
124+ renderer = SDL_CreateRenderer (win , -1 , 0 );
125+ if (!renderer )
126+ {
127+ printf ("Failed to create Renderer by SDL\n" );
128+ goto __exit ;
129+ }
130+
131+ // 创建纹理
132+ texture = SDL_CreateTexture (renderer , SDL_PIXELFORMAT_IYUV ,
133+ SDL_TEXTUREACCESS_STREAMING ,
134+ w_width ,
135+ w_height );
136+ if (!texture ) {
137+ printf ("SDL_CreateTexture Error: %s\n" ,SDL_GetError ());
138+ goto __exit ;
139+ }
140+
141+ int receive_frame_ret = 0 ;
142+
143+ // 读取数据
144+ while (av_read_frame (pFormatCtx , & packet ) >= 0 )
145+ {
146+ if (packet .stream_index == videoStream )
147+ {
148+ // 解码
149+ avcodec_send_packet (pCodecCtx , & packet );
150+ while (receive_frame_ret = avcodec_receive_frame (pCodecCtx , pFrame ) == 0 )
151+ {
152+ if (receive_frame_ret < 0 ) {
153+ printf ("avcodec_receive_frame error: %d\n" ,receive_frame_ret );
154+ goto __exit ;
155+ }
156+ SDL_UpdateYUVTexture (texture , NULL ,
157+ pFrame -> data [0 ], pFrame -> linesize [0 ],
158+ pFrame -> data [1 ], pFrame -> linesize [1 ],
159+ pFrame -> data [2 ], pFrame -> linesize [2 ]);
160+
161+ // set size of Window
162+ rect .x = 0 ;
163+ rect .y = 0 ;
164+ rect .w = pCodecCtx -> width ;
165+ rect .h = pCodecCtx -> height ;
166+
167+ SDL_RenderClear (renderer );
168+ SDL_RenderCopy (renderer , texture , NULL , & rect );
169+ SDL_RenderPresent (renderer );
170+ }
171+ }
172+
173+ av_packet_unref (& packet );
174+ }
175+
176+ __exit :
177+
178+ if (pFrame )
179+ {
180+ av_frame_free (& pFrame );
181+ }
182+
183+ if (pCodecCtx )
184+ {
185+ avcodec_close (pCodecCtx );
186+ }
187+
188+ if (pCodecParameters )
189+ {
190+ avcodec_parameters_free (& pCodecParameters );
191+ }
192+
193+ if (pFormatCtx )
194+ {
195+ avformat_close_input (& pFormatCtx );
196+ }
197+
198+ if (win )
199+ {
200+ SDL_DestroyWindow (win );
201+ }
202+
203+ if (renderer )
204+ {
205+ SDL_DestroyRenderer (renderer );
206+ }
207+
208+ if (texture )
209+ {
210+ SDL_DestroyTexture (texture );
211+ }
212+
213+ SDL_Quit ();
214+
215+ return ret ;
216+ }
0 commit comments