Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
preview-generator
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
mediaflix
preview-generator
Commits
3ba228ad
Commit
3ba228ad
authored
5 years ago
by
Janne Mareike Koschinski
Browse files
Options
Downloads
Patches
Plain Diff
make the code less bad
parent
5dea25aa
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
4
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
src/ffmpeg_api/api.rs
+344
-0
344 additions, 0 deletions
src/ffmpeg_api/api.rs
src/ffmpeg_api/enums.rs
+934
-0
934 additions, 0 deletions
src/ffmpeg_api/enums.rs
src/ffmpeg_api/mod.rs
+2
-0
2 additions, 0 deletions
src/ffmpeg_api/mod.rs
src/main.rs
+49
-71
49 additions, 71 deletions
src/main.rs
with
1329 additions
and
71 deletions
src/ffmpeg_api/api.rs
0 → 100644
+
344
−
0
View file @
3ba228ad
use
ffmpeg_dev
::
sys
as
ffi
;
use
failure
::
bail
;
use
enum_primitive
::
*
;
use
std
::
marker
::
PhantomData
;
use
fraction
::
Fraction
;
use
crate
::
ffmpeg_api
::
enums
::
*
;
// TODO: Use proper errors (with struct etc) for this
enum_from_primitive!
{
#[derive(Debug,
Copy,
Clone,
PartialEq)]
#[repr(i32)]
pub
enum
AVErrorKind
{
Unknown
=
ffi
::
AVERROR_EXPERIMENTAL
,
InputChanged
=
ffi
::
AVERROR_INPUT_CHANGED
,
OutputChanged
=
ffi
::
AVERROR_OUTPUT_CHANGED
}
}
pub
struct
AVFormatContext
{
base
:
*
mut
ffi
::
AVFormatContext
,
}
impl
<
'a
>
AVFormatContext
{
pub
fn
new
()
->
Result
<
Self
,
failure
::
Error
>
{
let
base
=
unsafe
{
ffi
::
avformat_alloc_context
()
};
if
base
.is_null
()
{
bail!
(
"avformat_alloc_context() failed"
);
}
Ok
(
AVFormatContext
{
base
})
}
// TODO: Just for testing
pub
unsafe
fn
raw
(
&
self
)
->
*
mut
ffi
::
AVFormatContext
{
self
.base
}
pub
fn
open_input
(
&
mut
self
,
path
:
&
str
)
->
Result
<
(),
failure
::
Error
>
{
match
unsafe
{
ffi
::
avformat_open_input
(
&
mut
self
.base
,
std
::
ffi
::
CString
::
new
(
path
)
.map_err
(|
_
|
failure
::
format_err!
(
"Could not convert path to c string"
))
?
.as_ptr
(),
std
::
ptr
::
null_mut
(),
std
::
ptr
::
null_mut
(),
)
}
{
0
=>
Ok
(()),
_
=>
bail!
(
"Could not open input"
)
}
}
pub
fn
streams
(
&
self
)
->
Vec
<
AVStream
>
{
return
unsafe
{
std
::
slice
::
from_raw_parts
(
(
*
self
.base
)
.streams
,
(
*
self
.base
)
.nb_streams
as
usize
,
)
}
.iter
()
.map
(|
stream
|
{
AVStream
::
new
(
unsafe
{
(
*
stream
)
.as_mut
()
}
.expect
(
"not null"
),
self
)
})
.collect
();
}
}
impl
Drop
for
AVFormatContext
{
fn
drop
(
&
mut
self
)
{
unsafe
{
ffi
::
avformat_free_context
(
self
.base
)
}
}
}
pub
struct
AVBuffer
{
base
:
*
mut
u8
,
size
:
usize
,
}
impl
AVBuffer
{
pub
fn
new
(
size
:
usize
)
->
Result
<
Self
,
failure
::
Error
>
{
let
base
=
unsafe
{
ffi
::
av_malloc
(
size
)
}
as
*
mut
u8
;
if
base
.is_null
()
{
bail!
(
"av_malloc() failed"
);
}
Ok
(
AVBuffer
{
base
,
size
})
}
pub
fn
empty
()
->
Self
{
AVBuffer
{
base
:
std
::
ptr
::
null_mut
(),
size
:
0
}
}
pub
fn
data
(
&
self
)
->
&
[
u8
]
{
unsafe
{
std
::
slice
::
from_raw_parts
(
self
.base
,
self
.size
)
}
}
pub
fn
data_mut
(
&
mut
self
)
->
&
[
u8
]
{
unsafe
{
std
::
slice
::
from_raw_parts_mut
(
self
.base
,
self
.size
)
}
}
}
pub
struct
AVFrame
{
base
:
*
mut
ffi
::
AVFrame
,
buffer
:
AVBuffer
,
}
impl
AVFrame
{
pub
fn
new
()
->
Result
<
Self
,
failure
::
Error
>
{
let
base
=
unsafe
{
ffi
::
av_frame_alloc
()
};
if
base
.is_null
()
{
bail!
(
"avformat_alloc_frame() failed"
);
}
Ok
(
AVFrame
{
base
,
buffer
:
AVBuffer
::
empty
()
})
}
// TODO: Just for testing
pub
unsafe
fn
as_mut
(
&
mut
self
)
->
&
mut
ffi
::
AVFrame
{
self
.base
.as_mut
()
.expect
(
"not null"
)
}
pub
fn
init
(
&
mut
self
,
width
:
i32
,
height
:
i32
,
format
:
AVPixelFormat
)
->
Result
<
(),
failure
::
Error
>
{
let
mut
base
=
unsafe
{
self
.base
.as_mut
()
}
.expect
(
"not null"
);
base
.width
=
width
;
base
.height
=
height
;
base
.format
=
format
as
ffi
::
AVPixelFormat
;
self
.buffer
=
AVBuffer
::
new
(
self
.size
())
?
;
unsafe
{
ffi
::
avpicture_fill
(
self
.base
as
*
mut
ffi
::
AVPicture
,
self
.buffer.base
as
*
mut
u8
,
self
.format
()
as
ffi
::
AVPixelFormat
,
self
.width
(),
self
.height
(),
)
};
Ok
(())
}
pub
fn
width
(
&
self
)
->
i32
{
let
base
=
unsafe
{
self
.base
.as_ref
()
}
.expect
(
"not null"
);
base
.width
}
pub
fn
height
(
&
self
)
->
i32
{
let
base
=
unsafe
{
self
.base
.as_ref
()
}
.expect
(
"not null"
);
base
.height
}
pub
fn
format
(
&
self
)
->
AVPixelFormat
{
let
base
=
unsafe
{
self
.base
.as_ref
()
}
.expect
(
"not null"
);
AVPixelFormat
::
from_i32
(
base
.format
)
.unwrap_or
(
AVPixelFormat
::
NONE
)
}
pub
fn
size
(
&
self
)
->
usize
{
unsafe
{
ffi
::
avpicture_get_size
(
self
.format
()
as
ffi
::
AVPixelFormat
,
self
.width
(),
self
.height
())
as
usize
}
}
pub
fn
key_frame
(
&
self
)
->
bool
{
let
base
=
unsafe
{
self
.base
.as_ref
()
}
.expect
(
"not null"
);
base
.key_frame
!=
0
}
pub
fn
pts
(
&
self
)
->
i64
{
let
base
=
unsafe
{
self
.base
.as_ref
()
}
.expect
(
"not null"
);
base
.pts
}
pub
fn
coded_picture_number
(
&
self
)
->
i32
{
let
base
=
unsafe
{
self
.base
.as_ref
()
}
.expect
(
"not null"
);
base
.coded_picture_number
}
pub
fn
display_picture_number
(
&
self
)
->
i32
{
let
base
=
unsafe
{
self
.base
.as_ref
()
}
.expect
(
"not null"
);
base
.display_picture_number
}
pub
fn
linesize
(
&
self
)
->
&
[
i32
]
{
let
base
=
unsafe
{
self
.base
.as_ref
()
}
.expect
(
"not null"
);
&
base
.linesize
}
pub
fn
data_ptr
(
&
self
)
->
*
const
*
const
u8
{
let
base
=
unsafe
{
self
.base
.as_ref
()
}
.expect
(
"not null"
);
base
.data
.as_ptr
()
as
*
const
*
const
u8
}
pub
fn
data_mut_ptr
(
&
mut
self
)
->
*
mut
*
mut
u8
{
let
base
=
unsafe
{
self
.base
.as_mut
()
}
.expect
(
"not null"
);
base
.data
.as_mut_ptr
()
as
*
mut
*
mut
u8
}
pub
fn
data
(
&
self
,
index
:
usize
)
->
&
[
u8
]
{
let
base
=
unsafe
{
self
.base
.as_ref
()
}
.expect
(
"not null"
);
unsafe
{
std
::
slice
::
from_raw_parts
(
base
.data
[
index
],
self
.size
())
}
}
pub
fn
data_mut
(
&
mut
self
,
index
:
usize
)
->
&
mut
[
u8
]
{
let
base
=
unsafe
{
self
.base
.as_mut
()
}
.expect
(
"not null"
);
unsafe
{
std
::
slice
::
from_raw_parts_mut
(
base
.data
[
index
],
self
.size
())
}
}
}
impl
Drop
for
AVFrame
{
fn
drop
(
&
mut
self
)
{
unsafe
{
ffi
::
av_frame_free
(
&
mut
self
.base
)
}
}
}
pub
struct
AVStream
<
'a
>
{
base
:
&
'a
mut
ffi
::
AVStream
,
phantom
:
PhantomData
<&
'a
AVFormatContext
>
,
}
impl
<
'a
>
AVStream
<
'a
>
{
fn
new
(
base
:
&
'a
mut
ffi
::
AVStream
,
_
:
&
'a
AVFormatContext
)
->
Self
{
return
AVStream
{
base
,
phantom
:
PhantomData
};
}
pub
fn
index
(
self
:
&
AVStream
<
'a
>
)
->
i32
{
self
.base.index
}
pub
fn
time_base
(
self
:
&
AVStream
<
'a
>
)
->
Fraction
{
Fraction
::
new
(
self
.base.time_base.num
as
u32
,
self
.base.time_base.den
as
u32
,
)
}
pub
fn
timestamp
(
self
:
&
AVStream
<
'a
>
,
timestamp
:
i64
)
->
std
::
time
::
Duration
{
std
::
time
::
Duration
::
from_millis
(
1000
*
timestamp
as
u64
*
self
.base.time_base.num
as
u64
/
self
.base.time_base.den
as
u64
)
}
pub
fn
duration
(
self
:
&
AVStream
<
'a
>
)
->
std
::
time
::
Duration
{
self
.timestamp
(
self
.base.duration
)
}
pub
fn
frame_count
(
self
:
&
AVStream
<
'a
>
)
->
i64
{
self
.base.nb_frames
}
pub
fn
discard
(
self
:
&
AVStream
<
'a
>
)
->
Option
<
AVDiscard
>
{
AVDiscard
::
from_i32
(
self
.base.discard
)
}
pub
fn
set_discard
(
self
:
&
mut
AVStream
<
'a
>
,
value
:
AVDiscard
)
{
self
.base.discard
=
value
as
ffi
::
AVDiscard
;
}
pub
fn
sample_aspect_ratio
(
self
:
&
AVStream
<
'a
>
)
->
Fraction
{
Fraction
::
new
(
self
.base.sample_aspect_ratio.num
as
u32
,
self
.base.sample_aspect_ratio.den
as
u32
,
)
}
pub
fn
codec_parameters
(
self
:
&
AVStream
<
'a
>
)
->
AVCodecParameters
{
AVCodecParameters
::
new
(
unsafe
{
self
.base.codecpar
.as_mut
()
}
.expect
(
"not null"
),
self
)
}
}
pub
struct
AVCodecParameters
<
'a
>
{
base
:
&
'a
mut
ffi
::
AVCodecParameters
,
phantom
:
PhantomData
<&
'a
AVStream
<
'a
>>
,
}
impl
<
'a
>
AVCodecParameters
<
'a
>
{
fn
new
(
base
:
&
'a
mut
ffi
::
AVCodecParameters
,
_
:
&
'a
AVStream
)
->
Self
{
return
AVCodecParameters
{
base
,
phantom
:
PhantomData
};
}
// TODO: Just for testing
pub
unsafe
fn
as_ref
(
&
self
)
->
&
ffi
::
AVCodecParameters
{
self
.base
}
pub
fn
codec_type
(
self
:
&
AVCodecParameters
<
'a
>
)
->
AVMediaType
{
AVMediaType
::
from_i32
(
self
.base.codec_type
)
.unwrap_or
(
AVMediaType
::
Unknown
)
}
pub
fn
codec_id
(
self
:
&
AVCodecParameters
<
'a
>
)
->
Option
<
AVCodecID
>
{
AVCodecID
::
from_u32
(
self
.base.codec_id
)
}
pub
fn
find_decoder
(
self
:
&
AVCodecParameters
<
'a
>
)
->
AVCodec
{
AVCodec
::
new
(
unsafe
{
ffi
::
avcodec_find_decoder
(
self
.base.codec_id
)
.as_mut
()
}
.expect
(
"Decoder not found"
),
self
,
)
}
}
pub
struct
AVCodec
<
'a
>
{
base
:
&
'a
mut
ffi
::
AVCodec
,
phantom
:
PhantomData
<&
'a
AVCodecParameters
<
'a
>>
,
}
impl
<
'a
>
AVCodec
<
'a
>
{
fn
new
(
base
:
&
'a
mut
ffi
::
AVCodec
,
_
:
&
'a
AVCodecParameters
)
->
Self
{
return
AVCodec
{
base
,
phantom
:
PhantomData
};
}
// TODO: Just for testing
pub
unsafe
fn
as_ref
(
&
self
)
->
&
ffi
::
AVCodec
{
self
.base
}
pub
fn
name
(
self
:
&
AVCodec
<
'a
>
)
->
std
::
string
::
String
{
String
::
from
(
unsafe
{
std
::
ffi
::
CStr
::
from_ptr
(
self
.base.name
)
}
.to_str
()
.unwrap
())
}
}
This diff is collapsed.
Click to expand it.
src/ffmpeg_api.rs
→
src/ffmpeg_api
/enums
.rs
+
934
−
0
View file @
3ba228ad
This diff is collapsed.
Click to expand it.
src/ffmpeg_api/mod.rs
0 → 100644
+
2
−
0
View file @
3ba228ad
pub
(
crate
)
mod
enums
;
pub
(
crate
)
mod
api
;
This diff is collapsed.
Click to expand it.
src/main.rs
+
49
−
71
View file @
3ba228ad
use
ffmpeg_dev
::
sys
as
ffi
;
use
ffmpeg_dev
::
sys
as
ffi
;
use
enum_primitive
::
*
;
use
std
::
collections
::
HashMap
;
mod
ffmpeg_api
;
pub
(
crate
)
mod
ffmpeg_api
;
use
ffmpeg_api
::
*
;
use
crate
::
ffmpeg_api
::
enums
::
*
;
use
crate
::
ffmpeg_api
::
api
::
*
;
fn
main
()
->
Result
<
(),
std
::
io
::
Error
>
{
fn
main
()
->
Result
<
(),
std
::
io
::
Error
>
{
let
mut
before
=
std
::
time
::
SystemTime
::
now
();
let
mut
before
=
std
::
time
::
SystemTime
::
now
();
...
@@ -31,36 +30,26 @@ fn main() -> Result<(), std::io::Error> {
...
@@ -31,36 +30,26 @@ fn main() -> Result<(), std::io::Error> {
local_codec
.name
()
local_codec
.name
()
);
);
// TODO: HERE BE DRAGONS
let
mut
output_frame
=
AVFrame
::
new
()
.unwrap_or_else
(|
error
|
{
panic!
(
"Could not create output frame: {:?}"
,
error
)
let
output_frame
=
unsafe
{
});
ffi
::
av_frame_alloc
()
.as_mut
()
output_frame
.init
(
160
,
90
,
AVPixelFormat
::
RGB24
)
.unwrap_or_else
(|
error
|
{
}
.expect
(
"not null"
);
panic!
(
"Could not init output frame: {:?}"
,
error
)
});
let
num_bytes
:
usize
=
unsafe
{
ffi
::
avpicture_get_size
(
ffi
::
AVPixelFormat_AV_PIX_FMT_RGB24
,
160
,
90
)
as
usize
};
let
output_frame_buffer
=
unsafe
{
(
ffi
::
av_malloc
(
num_bytes
)
as
*
mut
u8
)
.as_ref
()
}
.expect
(
"not null"
);
unsafe
{
ffi
::
avpicture_fill
(
output_frame
as
*
mut
ffi
::
AVFrame
as
*
mut
ffi
::
AVPicture
,
output_frame_buffer
,
ffi
::
AVPixelFormat_AV_PIX_FMT_RGB24
,
160
,
90
,
);
}
match
codec_parameters
.codec_type
()
{
match
codec_parameters
.codec_type
()
{
AVMediaType
::
Video
=>
{
AVMediaType
::
Video
=>
{
// TODO: HERE BE DRAGONS
let
avc_ctx
:
&
mut
ffi
::
AVCodecContext
=
unsafe
{
let
avc_ctx
:
&
mut
ffi
::
AVCodecContext
=
unsafe
{
ffi
::
avcodec_alloc_context3
(
local_codec
.as_ref
())
.as_mut
()
ffi
::
avcodec_alloc_context3
(
local_codec
.as_ref
())
.as_mut
()
}
.expect
(
"not null"
);
}
.expect
(
"not null"
);
avc_ctx
.skip_loop_filter
=
ffi
::
AVDiscard_AVDISCARD_NONKEY
;
avc_ctx
.skip_idct
=
ffi
::
AVDiscard_AVDISCARD_NONKEY
;
avc_ctx
.skip_frame
=
ffi
::
AVDiscard_AVDISCARD_NONKEY
;
unsafe
{
unsafe
{
ffi
::
avcodec_parameters_to_context
(
avc_ctx
,
codec_parameters
.as_ref
());
ffi
::
avcodec_parameters_to_context
(
avc_ctx
,
codec_parameters
.as_ref
());
ffi
::
avcodec_open2
(
avc_ctx
,
local_codec
.as_ref
(),
std
::
ptr
::
null_mut
());
ffi
::
avcodec_open2
(
avc_ctx
,
local_codec
.as_ref
(),
std
::
ptr
::
null_mut
());
...
@@ -70,49 +59,39 @@ fn main() -> Result<(), std::io::Error> {
...
@@ -70,49 +59,39 @@ fn main() -> Result<(), std::io::Error> {
ffi
::
av_packet_alloc
()
.as_mut
()
ffi
::
av_packet_alloc
()
.as_mut
()
}
.expect
(
"not null"
);
}
.expect
(
"not null"
);
let
frame
:
&
mut
ffi
::
AVFrame
=
unsafe
{
let
mut
frame
=
AVFrame
::
new
()
.unwrap_or_else
(|
error
|
{
ffi
::
av_frame_alloc
()
.as_mut
()
panic!
(
"Could not create input frame: {:?}"
,
error
)
}
.expect
(
"not null"
);
});
avc_ctx
.skip_loop_filter
=
ffi
::
AVDiscard_AVDISCARD_NONKEY
;
avc_ctx
.skip_idct
=
ffi
::
AVDiscard_AVDISCARD_NONKEY
;
avc_ctx
.skip_frame
=
ffi
::
AVDiscard_AVDISCARD_NONKEY
;
let
mut
i
=
0
;
let
mut
i
=
0
;
println!
(
"Time: {:#?}"
,
before
.elapsed
()
.unwrap
());
println!
(
"Time: {:#?}"
,
before
.elapsed
()
.unwrap
());
before
=
std
::
time
::
SystemTime
::
now
();
before
=
std
::
time
::
SystemTime
::
now
();
let
mut
sws_context
:
*
mut
ffi
::
SwsContext
=
std
::
ptr
::
null_mut
();
while
unsafe
{
ffi
::
av_read_frame
(
avformat_context
.raw
(),
packet
)
}
>=
0
&&
i
<
10
{
while
unsafe
{
ffi
::
av_read_frame
(
avformat_context
.raw
(),
packet
)
}
>=
0
&&
i
<
10
{
if
packet
.stream_index
==
stream
.index
()
{
if
packet
.stream_index
==
stream
.index
()
{
unsafe
{
unsafe
{
ffi
::
avcodec_send_packet
(
avc_ctx
,
packet
);
ffi
::
avcodec_send_packet
(
avc_ctx
,
packet
);
}
}
while
unsafe
{
ffi
::
avcodec_receive_frame
(
avc_ctx
,
frame
)
}
>=
0
{
while
unsafe
{
ffi
::
avcodec_receive_frame
(
avc_ctx
,
frame
.as_mut
())
}
>=
0
{
let
key_frame
=
frame
.key_frame
!=
0
;
let
frame_index
=
frame
.coded_picture_number
;
println!
(
println!
(
"Frame {}: {:?} @ {}"
,
"Frame {}: {:?} @ {}"
,
frame
_index
,
frame
.coded_picture_number
()
,
stream
.timestamp
(
frame
.pts
as
i64
),
stream
.timestamp
(
frame
.pts
()
),
key_frame
frame
.
key_frame
()
);
);
println!
(
"Reading Time: {:#?}"
,
before
.elapsed
()
.unwrap
());
println!
(
"Reading Time: {:#?}"
,
before
.elapsed
()
.unwrap
());
before
=
std
::
time
::
SystemTime
::
now
();
before
=
std
::
time
::
SystemTime
::
now
();
if
sws_context
.is_null
()
{
/*
sws_context
=
unsafe
{
if frame.width == last_width && frame.height == last_height && (frame.format as AVPixelFormat) == last_format {
}
*/
let
sws_context
:
&
mut
ffi
::
SwsContext
=
unsafe
{
ffi
::
sws_getContext
(
ffi
::
sws_getContext
(
frame
.width
,
frame
.width
()
,
frame
.height
,
frame
.height
()
,
frame
.format
as
ffi
::
AVPixelFormat
,
frame
.format
()
as
ffi
::
AVPixelFormat
,
160
,
160
,
90
,
90
,
ffi
::
AVPixelFormat_AV_PIX_FMT_RGB24
,
ffi
::
AVPixelFormat_AV_PIX_FMT_RGB24
,
...
@@ -122,31 +101,30 @@ fn main() -> Result<(), std::io::Error> {
...
@@ -122,31 +101,30 @@ fn main() -> Result<(), std::io::Error> {
std
::
ptr
::
null
(),
std
::
ptr
::
null
(),
)
.as_mut
()
)
.as_mut
()
}
.expect
(
"not null"
);
}
.expect
(
"not null"
);
}
let
success
=
unsafe
{
let
success
=
unsafe
{
ffi
::
sws_scale
(
ffi
::
sws_scale
(
sws_context
,
sws_context
,
frame
.data
.as
_ptr
()
as
*
const
*
const
u8
,
frame
.data_ptr
(),
&
frame
.linesize
[
0
]
,
frame
.linesize
()
.as_ptr
()
,
0
,
0
,
frame
.height
,
frame
.height
()
,
&
output_frame
.data
[
0
]
,
output_frame
.data
_mut_ptr
()
,
&
output_frame
.linesize
[
0
]
,
output_frame
.linesize
()
.as_ptr
()
,
)
)
};
};
println!
(
"success: {}
, size: {}"
,
success
,
num_byte
s
);
println!
(
"success: {}
"
,
succes
s
);
println!
(
"Processing Time: {:#?}"
,
before
.elapsed
()
.unwrap
());
println!
(
"Processing Time: {:#?}"
,
before
.elapsed
()
.unwrap
());
before
=
std
::
time
::
SystemTime
::
now
();
before
=
std
::
time
::
SystemTime
::
now
();
if
success
>
0
{
if
success
>
0
{
image
::
save_buffer
(
image
::
save_buffer
(
format!
(
"/home/janne/Workspace/justflix/data/test/image_{}.png"
,
i
),
format!
(
"/home/janne/Workspace/justflix/data/test/image_{}.png"
,
i
),
unsafe
{
output_frame
.data
(
0
),
std
::
slice
::
from_raw_parts
(
output_frame
.data
[
0
],
num_bytes
)
output_frame
.width
()
as
u32
,
},
output_frame
.height
()
as
u32
,
160
,
90
,
image
::
ColorType
::
Rgb8
,
image
::
ColorType
::
Rgb8
,
)
.unwrap
();
)
.unwrap
();
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment