xref: /haiku/src/apps/haiku3d/texture/VideoFileTexture.cpp (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
1 /*
2  * Copyright 2008, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  * 		Alexandre Deckner <alex@zappotek.com>
7  */
8 
9 #include "VideoFileTexture.h"
10 
11 #include <Bitmap.h>
12 #include <Entry.h>
13 #include <MediaFile.h>
14 #include <MediaTrack.h>
15 
16 #include <GL/gl.h>
17 #include <GL/glu.h>
18 #include <string.h>
19 #include <stdio.h>
20 
21 
22 VideoFileTexture::VideoFileTexture(const char* fileName)
23 	:
24 	Texture(),
25 	fMediaFile(NULL),
26 	fVideoTrack(NULL),
27 	fVideoBitmap(NULL)
28 {
29 	_Load(fileName);
30 }
31 
32 
33 VideoFileTexture::~VideoFileTexture()
34 {
35 	delete fVideoBitmap;
36 
37 	if (fMediaFile != NULL) {
38 		fMediaFile->ReleaseAllTracks();
39 		fMediaFile->CloseFile();
40 		delete fMediaFile;
41 	}
42 }
43 
44 
45 void
46 VideoFileTexture::_Load(const char* fileName)
47 {
48 	BEntry entry(fileName);
49 	entry_ref ref;
50 	entry.GetRef(&ref);
51 
52 	fMediaFile = new BMediaFile(&ref);
53 	status_t err = fMediaFile->InitCheck();
54 	if (err != B_OK) {
55 		printf("cannot contruct BMediaFile object -- %s\n", strerror(err));
56 		return;
57 	}
58 
59 	int32 trackCount = fMediaFile->CountTracks();
60 
61 	for (int32 i = 0; i < trackCount; i++) {
62 		BMediaTrack* track = fMediaFile->TrackAt(i);
63 		if (track == NULL) {
64 			printf("cannot contruct BMediaTrack object\n");
65 			return;
66 		}
67 
68 		// get the encoded format
69 		media_format format;
70 		err = track->EncodedFormat(&format);
71 		if (err != B_OK) {
72 			printf("BMediaTrack::EncodedFormat error -- %s\n", strerror(err));
73 			return;
74 		}
75 
76 		if (format.type == B_MEDIA_ENCODED_VIDEO) {
77 			fVideoTrack = track;
78 			// allocate a bitmap large enough to contain the decoded frame.
79 			BRect bounds(0.0, 0.0,
80 				format.u.encoded_video.output.display.line_width - 1.0,
81 				format.u.encoded_video.output.display.line_count - 1.0);
82 			fVideoBitmap = new BBitmap(bounds, B_RGB32);
83 
84 			// specifiy the decoded format. we derive this information from
85 			// the encoded format.
86 			memset(&format, 0, sizeof(media_format));
87 			format.u.raw_video.last_active = (int32) (bounds.Height() - 1.0);
88 			format.u.raw_video.orientation = B_VIDEO_TOP_LEFT_RIGHT;
89 			format.u.raw_video.pixel_width_aspect = 1;
90 			format.u.raw_video.pixel_height_aspect = 3;
91 			format.u.raw_video.display.format = fVideoBitmap->ColorSpace();
92 			format.u.raw_video.display.line_width = (int32) bounds.Width();
93 			format.u.raw_video.display.line_count = (int32) bounds.Height();
94 			format.u.raw_video.display.bytes_per_row
95 				= fVideoBitmap->BytesPerRow();
96 
97 			err = fVideoTrack->DecodedFormat(&format);
98 			if (err != B_OK) {
99 				printf("error with BMediaTrack::DecodedFormat() -- %s\n",
100 					strerror(err));
101 				return;
102 			}
103 
104 			// Create Texture
105 			glGenTextures(1, &fId);
106 			glBindTexture(GL_TEXTURE_2D, fId);
107 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
108 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
109 			glTexImage2D(GL_TEXTURE_2D, 0, 4,
110 				(int) fVideoBitmap->Bounds().Width() + 1,
111 				(int) fVideoBitmap->Bounds().Height() + 1,
112 				0, GL_BGRA, GL_UNSIGNED_BYTE, fVideoBitmap->Bits());
113 		}
114 	}
115 }
116 
117 
118 void
119 VideoFileTexture::Update(float /*dt*/) {
120 	// TODO loop
121 	int64 frameCount = 0;
122 	media_header mh;
123 	status_t err
124 		= fVideoTrack->ReadFrames(fVideoBitmap->Bits(), &frameCount, &mh);
125 	if (err) {
126 		printf("BMediaTrack::ReadFrames error -- %s\n", strerror(err));
127 		return;
128 	}
129 
130 	glBindTexture(GL_TEXTURE_2D, fId);
131 	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
132 		(int)fVideoBitmap->Bounds().Width() + 1,
133 		(int)fVideoBitmap->Bounds().Height() + 1,
134 		GL_BGRA, GL_UNSIGNED_BYTE, fVideoBitmap->Bits());
135 }
136 
137