Skip to content

Commit 9664cd4

Browse files
committed
Code compiles, now working on getting configure.ac fixed
1 parent 302d0cc commit 9664cd4

File tree

4 files changed

+195
-26
lines changed

4 files changed

+195
-26
lines changed

Headers/AppKit/NSMovie.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ APPKIT_EXPORT_CLASS
4141
@interface NSMovie : NSObject <NSCopying, NSCoding>
4242
{
4343
@private
44-
NSData* _movie;
45-
NSURL* _url;
44+
NSData* _movie;
45+
NSURL* _url;
46+
BOOL _tmp;
4647
}
4748

4849
+ (NSArray*) movieUnfilteredFileTypes;

Headers/AppKit/NSMovieView.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232

3333
#import <AppKit/NSView.h>
3434

35+
#include <libavcodec/avcodec.h>
36+
#include <libavformat/avformat.h>
37+
#include <libswscale/swscale.h>
38+
#include <libavutil/imgutils.h>
39+
3540
@class NSMovie;
3641

3742
typedef enum {
@@ -56,6 +61,18 @@ APPKIT_EXPORT_CLASS
5661
unsigned int editable: 1;
5762
unsigned int reserved: 24;
5863
} _flags;
64+
BOOL _playing;
65+
NSTimer *_decodeTimer;
66+
67+
// libav specific...
68+
NSImage *_currentFrame;
69+
AVFormatContext *_formatContext;
70+
AVCodecContext *_codecContext;
71+
AVFrame *_avframe;
72+
AVFrame *_avframeRGB;
73+
struct SwsContext *_swsCtx;
74+
int _videoStreamIndex;
75+
uint8_t *_buffer;
5976
}
6077

6178
- (void) setMovie: (NSMovie*)movie;

Source/NSMovie.m

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,38 @@
3030
#import <Foundation/NSCoder.h>
3131
#import <Foundation/NSData.h>
3232
#import <Foundation/NSURL.h>
33+
#import <Foundation/NSFileManager.h>
34+
#import <Foundation/NSUUID.h>
35+
3336
#import "AppKit/NSMovie.h"
3437
#import "AppKit/NSPasteboard.h"
3538

39+
NSString *_writeDataToTempFile(NSData *data)
40+
{
41+
NSString *tempDirectory = NSTemporaryDirectory();
42+
NSString *filename = [NSString stringWithFormat: @"tmpfile-%@.dat", [[NSUUID UUID] UUIDString]];
43+
NSString *filepath = [tempDirectory stringByAppendingPathComponent: filename];
44+
NSError *error = nil;
45+
46+
BOOL success = [data writeToFile: filepath options: NSDataWritingAtomic error: &error];
47+
if (success)
48+
{
49+
return nil;
50+
}
51+
52+
return filepath;
53+
}
54+
3655
@implementation NSMovie
3756

3857
+ (NSArray*) movieUnfilteredFileTypes
3958
{
40-
return [NSArray arrayWithObject: @"mov"];
59+
return [NSArray arrayWithObjects: @"mp4", @"mov", @"avi", @"flv", @"mkv", @"webm", nil ];
4160
}
4261

4362
+ (NSArray*) movieUnfilteredPasteboardTypes
4463
{
45-
// FIXME
46-
return [NSArray arrayWithObject: @"QuickTimeMovie"];
64+
return [self movieUnfilteredFileTypes];
4765
}
4866

4967
+ (BOOL) canInitWithPasteboard: (NSPasteboard*)pasteboard
@@ -61,31 +79,33 @@ - (id) initWithData: (NSData *)movie
6179
RELEASE(self);
6280
return nil;
6381
}
64-
65-
[super init];
66-
ASSIGN(_movie, movie);
6782

83+
self = [super init];
84+
if (self != nil)
85+
{
86+
NSString *filepath = _writeDataToTempFile(_movie);
87+
88+
_url = [NSURL fileURLWithPath: filepath];
89+
_tmp = YES;
90+
ASSIGN(_movie, movie);
91+
}
92+
6893
return self;
6994
}
7095

7196
- (id) initWithMovie: (void*)movie
7297
{
73-
//FIXME
74-
75-
return self;
98+
return [self initWithData: movie];
7699
}
77100

78101
- (id) initWithURL: (NSURL*)url byReference: (BOOL)byRef
79102
{
80-
NSData* data = [url resourceDataUsingCache: YES];
81-
82-
self = [self initWithData: data];
83-
84-
if (byRef)
103+
self = [super init];
104+
if (self != nil)
85105
{
86106
ASSIGN(_url, url);
87107
}
88-
108+
89109
return self;
90110
}
91111

@@ -94,12 +114,11 @@ - (id) initWithPasteboard: (NSPasteboard*)pasteboard
94114
NSString *type;
95115
NSData* data;
96116

97-
type = [pasteboard availableTypeFromArray:
98-
[object_getClass(self) movieUnfilteredPasteboardTypes]];
117+
type =
118+
[pasteboard availableTypeFromArray:
119+
[object_getClass(self) movieUnfilteredPasteboardTypes]];
99120
if (type == nil)
100121
{
101-
//NSArray *array = [pasteboard propertyListForType: NSFilenamesPboardType];
102-
// FIXME
103122
data = nil;
104123
}
105124
else
@@ -120,9 +139,11 @@ - (id) initWithPasteboard: (NSPasteboard*)pasteboard
120139

121140
- (void) dealloc
122141
{
142+
_tmp = NO;
143+
[[NSFileManager defaultManager] removeFileAtPath: [_url path] error: nil];
123144
TEST_RELEASE(_url);
124145
TEST_RELEASE(_movie);
125-
146+
126147
[super dealloc];
127148
}
128149

Source/NSMovieView.m

Lines changed: 134 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,125 @@
2828

2929
#import <Foundation/NSArray.h>
3030
#import <Foundation/NSData.h>
31+
#import <Foundation/NSTimer.h>
3132
#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"
3238
#import "AppKit/NSMovie.h"
3339
#import "AppKit/NSMovieView.h"
3440
#import "AppKit/NSPasteboard.h"
3541

3642
@implementation NSMovieView
3743

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+
38146
- (void) setMovie: (NSMovie*)movie
39147
{
40148
ASSIGN(_movie, movie);
149+
[self _prepareDecoder];
41150
}
42151

43152
- (NSMovie*) movie
@@ -47,18 +156,39 @@ - (NSMovie*) movie
47156

48157
- (void) start: (id)sender
49158
{
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];
51169
}
52170

53171
- (void) stop: (id)sender
54172
{
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);
56187
}
57188

58189
- (BOOL) isPlaying
59190
{
60-
//FIXME
61-
return NO;
191+
return _playing;
62192
}
63193

64194
- (void) gotoPosterFrame: (id)sender

0 commit comments

Comments
 (0)