28
28
29
29
#import < Foundation/NSArray.h>
30
30
#import < Foundation/NSData.h>
31
+ #import < Foundation/NSTimer.h>
31
32
#import < Foundation/NSURL.h>
33
+
34
+ #import " AppKit/NSColor.h"
35
+ #import " AppKit/NSGraphics.h"
36
+ #import " AppKit/NSImage.h"
37
+ #import " AppKit/NSImageRep.h"
32
38
#import " AppKit/NSMovie.h"
33
39
#import " AppKit/NSMovieView.h"
34
40
#import " AppKit/NSPasteboard.h"
35
41
36
42
@implementation NSMovieView
37
43
44
+ // private method to display frames...
45
+ - (void ) _updateImage : (NSImage *)image
46
+ {
47
+ _currentFrame = image;
48
+ [self setNeedsDisplay: YES ];
49
+ }
50
+
51
+ - (void ) _prepareDecoder
52
+ {
53
+ NSString *moviePath = [[_movie URL ] path ];
54
+
55
+ _formatContext = avformat_alloc_context ();
56
+ if (avformat_open_input (&_formatContext, [moviePath UTF8String ], NULL , NULL ) != 0 ) return ;
57
+ if (avformat_find_stream_info (_formatContext, NULL ) < 0 ) return ;
58
+
59
+ _videoStreamIndex = -1 ;
60
+ for (int i = 0 ; i < _formatContext->nb_streams ; i++)
61
+ {
62
+ if (_formatContext->streams [i]->codecpar ->codec_type == AVMEDIA_TYPE_VIDEO)
63
+ {
64
+ _videoStreamIndex = i;
65
+ break ;
66
+ }
67
+ }
68
+
69
+ if (_videoStreamIndex == -1 ) return ;
70
+
71
+ AVCodecParameters *codecPar = _formatContext->streams [_videoStreamIndex]->codecpar ;
72
+ const AVCodec *codec = avcodec_find_decoder (codecPar->codec_id );
73
+
74
+ _codecContext = avcodec_alloc_context3 (codec);
75
+ avcodec_parameters_to_context (_codecContext, codecPar);
76
+ if (avcodec_open2 (_codecContext, codec, NULL ) < 0 ) return ;
77
+
78
+ _avframe = av_frame_alloc ();
79
+ _avframeRGB = av_frame_alloc ();
80
+
81
+ int numBytes = av_image_get_buffer_size (AV_PIX_FMT_RGB24, _codecContext->width , _codecContext->height , 1 );
82
+ _buffer = (uint8_t *)av_malloc (numBytes * sizeof (uint8_t ));
83
+ av_image_fill_arrays (_avframeRGB->data , _avframeRGB->linesize , _buffer, AV_PIX_FMT_RGB24,
84
+ _codecContext->width , _codecContext->height , 1 );
85
+
86
+ _swsCtx = sws_getContext (_codecContext->width , _codecContext->height , _codecContext->pix_fmt ,
87
+ _codecContext->width , _codecContext->height , AV_PIX_FMT_RGB24,
88
+ SWS_BILINEAR, NULL , NULL , NULL );
89
+
90
+ }
91
+
92
+ - (void ) _decodeAndDisplayNextFrame
93
+ {
94
+ AVPacket packet;
95
+
96
+ av_init_packet (&packet);
97
+ packet.data = NULL ;
98
+ packet.size = 0 ;
99
+
100
+ while (av_read_frame (_formatContext, &packet) >= 0 )
101
+ {
102
+ if (!_playing) break ;
103
+
104
+ if (packet.stream_index == _videoStreamIndex)
105
+ {
106
+ avcodec_send_packet (_codecContext, &packet);
107
+ if (avcodec_receive_frame (_codecContext, _avframe) == 0 )
108
+ {
109
+ sws_scale (_swsCtx, (const uint8_t * const *)_avframe->data , _avframe->linesize , 0 ,
110
+ _codecContext->height , _avframeRGB->data , _avframeRGB->linesize );
111
+
112
+ NSBitmapImageRep *rep = [[NSBitmapImageRep alloc ]
113
+ initWithBitmapDataPlanes: _avframeRGB->data
114
+ pixelsWide: _codecContext->width
115
+ pixelsHigh: _codecContext->height
116
+ bitsPerSample: 8
117
+ samplesPerPixel: 3
118
+ hasAlpha: NO
119
+ isPlanar: NO
120
+ colorSpaceName: NSCalibratedRGBColorSpace
121
+ bytesPerRow: _avframeRGB->linesize[0 ]
122
+ bitsPerPixel: 24 ];
123
+
124
+ NSImage *image = [[NSImage alloc ] initWithSize: NSMakeSize (_codecContext->width, _codecContext->height)];
125
+ [image addRepresentation: rep];
126
+
127
+ [self performSelectorOnMainThread: @selector (_updateImage: )
128
+ withObject: image
129
+ waitUntilDone: NO ];
130
+ break ;
131
+ }
132
+ }
133
+ av_packet_unref (&packet);
134
+ }
135
+ }
136
+
137
+ - (void ) drawRect : (NSRect )dirtyRect
138
+ {
139
+ [super drawRect: dirtyRect];
140
+ if (_currentFrame)
141
+ {
142
+ [_currentFrame drawInRect: [self bounds ]];
143
+ }
144
+ }
145
+
38
146
- (void ) setMovie : (NSMovie *)movie
39
147
{
40
148
ASSIGN (_movie, movie);
149
+ [self _prepareDecoder ];
41
150
}
42
151
43
152
- (NSMovie *) movie
@@ -47,18 +156,39 @@ - (NSMovie*) movie
47
156
48
157
- (void ) start : (id )sender
49
158
{
50
- // FIXME
159
+ _playing = YES ;
160
+ _rate = 1.0 / 30.0 ;
161
+ _volume = 1.0 ;
162
+
163
+ _decodeTimer =
164
+ [NSTimer scheduledTimerWithTimeInterval: _rate
165
+ target: self
166
+ selector: @selector (decodeAndDisplayNextFrame )
167
+ userInfo: nil
168
+ repeats: YES ];
51
169
}
52
170
53
171
- (void ) stop : (id )sender
54
172
{
55
- // FIXME
173
+ _playing = NO ;
174
+
175
+ if (_decodeTimer)
176
+ {
177
+ [_decodeTimer invalidate ];
178
+ _decodeTimer = nil ;
179
+ }
180
+
181
+ if (_avframe) av_frame_free (&_avframe);
182
+ if (_avframeRGB) av_frame_free (&_avframeRGB);
183
+ if (_buffer) av_free (_buffer);
184
+ if (_codecContext) avcodec_free_context (&_codecContext);
185
+ if (_formatContext) avformat_close_input (&_formatContext);
186
+ if (_swsCtx) sws_freeContext (_swsCtx);
56
187
}
57
188
58
189
- (BOOL ) isPlaying
59
190
{
60
- // FIXME
61
- return NO ;
191
+ return _playing;
62
192
}
63
193
64
194
- (void ) gotoPosterFrame : (id )sender
0 commit comments