
Recherche avancée
Autres articles (76)
-
Personnaliser en ajoutant son logo, sa bannière ou son image de fond
5 septembre 2013, parCertains thèmes prennent en compte trois éléments de personnalisation : l’ajout d’un logo ; l’ajout d’une bannière l’ajout d’une image de fond ;
-
Ecrire une actualité
21 juin 2013, parPrésentez les changements dans votre MédiaSPIP ou les actualités de vos projets sur votre MédiaSPIP grâce à la rubrique actualités.
Dans le thème par défaut spipeo de MédiaSPIP, les actualités sont affichées en bas de la page principale sous les éditoriaux.
Vous pouvez personnaliser le formulaire de création d’une actualité.
Formulaire de création d’une actualité Dans le cas d’un document de type actualité, les champs proposés par défaut sont : Date de publication ( personnaliser la date de publication ) (...) -
Publier sur MédiaSpip
13 juin 2013Puis-je poster des contenus à partir d’une tablette Ipad ?
Oui, si votre Médiaspip installé est à la version 0.2 ou supérieure. Contacter au besoin l’administrateur de votre MédiaSpip pour le savoir
Sur d’autres sites (9132)
-
Screen Capture with FFMPEG and Google Native Client
18 juillet 2016, par Mohammad Abu MusaI am building a screen recorder that is based on Native Client for Google, I have ffmpeg installed and ready but I do not have experience programming in ffmpeg. so I am looking for tips to understand how to build this recorder.
My goal is to make a screen recorder and export videos as webm files, I have all the required libraries I just could not find any code examples to hack on
This is what I achieved so far
#define __STDC_LIMIT_MACROS
#include
#include <iostream>
#include
#include
#include <sstream>
#include
#include <vector>
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/var_dictionary.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppb_console.h"
#include "ppapi/cpp/input_event.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/rect.h"
#include "ppapi/cpp/var.h"
#include "ppapi/cpp/var_array_buffer.h"
// Begin File IO headers
#include "ppapi/c/pp_stdint.h"
#include "ppapi/c/ppb_file_io.h"
#include "ppapi/cpp/directory_entry.h"
#include "ppapi/cpp/file_io.h"
#include "ppapi/cpp/file_ref.h"
#include "ppapi/cpp/file_system.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/message_loop.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/var.h"
#include "ppapi/cpp/var_array.h"
#include "ppapi/utility/completion_callback_factory.h"
#include "ppapi/utility/threading/simple_thread.h"
#ifndef INT32_MAX
#define INT32_MAX (0x7FFFFFFF)
#endif
#ifdef WIN32
#undef min
#undef max
#undef PostMessage
// Allow 'this' in initializer list
#pragma warning(disable : 4355)
#endif
namespace {
typedef std::vector StringVector;
}
//End File IO headers
extern "C" {
#include <libavcodec></libavcodec>avcodec.h>
#include <libswscale></libswscale>swscale.h>
#include <libavformat></libavformat>avformat.h>
#include <libavutil></libavutil>imgutils.h>
}
const char* file_name = "/file.txt";
const char* video_name = "/video.mpeg";
const char* file_text = "Echo from NaCl: ";
/**
* Pixel formats and codecs
*/
static const AVPixelFormat sourcePixelFormat = AV_PIX_FMT_BGR24;
static const AVPixelFormat destPixelFormat = AV_PIX_FMT_YUV420P;
static const AVCodecID destCodec = AV_CODEC_ID_MPEG2VIDEO;
class RecorderInstance: public pp::Instance {
public:
explicit RecorderInstance(PP_Instance instance) :
pp::Instance(instance), callback_factory_(this), file_system_(this,
PP_FILESYSTEMTYPE_LOCALPERSISTENT), file_system_ready_(
false), file_thread_(this) {
}
virtual ~RecorderInstance() {
file_thread_.Join();
}
virtual bool Init(uint32_t /*argc*/, const char * /*argn*/[],
const char * /*argv*/[]) {
file_thread_.Start();
file_thread_.message_loop().PostWork(
callback_factory_.NewCallback(
&RecorderInstance::OpenFileSystem));
avcodec_register_all(); // mandatory to register ffmpeg functions
return true;
}
private:
pp::CompletionCallbackFactory<recorderinstance> callback_factory_;
pp::FileSystem file_system_;
// Indicates whether file_system_ was opened successfully. We only read/write
// this on the file_thread_.
bool file_system_ready_;
pp::SimpleThread file_thread_;
virtual void HandleMessage(const pp::Var& var_message) {
if (!var_message.is_dictionary()) {
LogToConsole(PP_LOGLEVEL_ERROR, pp::Var("Invalid message!"));
return;
}
pp::VarDictionary dict_message(var_message);
std::string command = dict_message.Get("message").AsString();
if (command == "sendFrame") {
pp::VarArrayBuffer data(dict_message.Get("data"));
uint width = 600;
uint height = 800;
uint8_t endcode[] = { 0, 0, 1, 0xb7 };
/**
* Create an encoder and open it
*/
avcodec_register_all();
AVCodec *h264encoder = avcodec_find_encoder(destCodec);
AVCodecContext *h264encoderContext = avcodec_alloc_context3(
h264encoder);
h264encoderContext->pix_fmt = destPixelFormat;
h264encoderContext->width = width;
h264encoderContext->height = height;
if (avcodec_open2(h264encoderContext, h264encoder, NULL) < 0) {
ShowErrorMessage("Cannot open codec" ,-1);
return;
}
/**
* Create a stream
*/
AVFormatContext *cv2avFormatContext = avformat_alloc_context();
AVStream *h264outputstream = avformat_new_stream(cv2avFormatContext,
h264encoder);
AVFrame *sourceAvFrame = av_frame_alloc(), *destAvFrame =
av_frame_alloc();
int got_frame;
FILE* videoOutFile = fopen("video", "wb");
/**
* Prepare the conversion context
*/
SwsContext *bgr2yuvcontext = sws_getContext(width, height,
sourcePixelFormat, width, height, destPixelFormat,
SWS_BICUBIC, NULL, NULL, NULL);
int framesToEncode = 100;
/**
* Convert and encode frames
*/
for (uint i = 0; i < framesToEncode; i++) {
/**
* Allocate source frame, i.e. input to sws_scale()
*/
av_image_alloc(sourceAvFrame->data, sourceAvFrame->linesize,
width, height, sourcePixelFormat, 1);
/**
* Copy image data into AVFrame from cv::Mat
*/
for (uint32_t h = 0; h < height; h++)
memcpy(
&(sourceAvFrame->data[0][h
* sourceAvFrame->linesize[0]]),
&(data), width * 3);
/**
* Allocate destination frame, i.e. output from sws_scale()
*/
av_image_alloc(destAvFrame->data, destAvFrame->linesize, width,
height, destPixelFormat, 1);
sws_scale(bgr2yuvcontext, sourceAvFrame->data,
sourceAvFrame->linesize, 0, height, destAvFrame->data,
destAvFrame->linesize);
sws_freeContext(bgr2yuvcontext);
/**
* Prepare an AVPacket and set buffer to NULL so that it'll be allocated by FFmpeg
*/
AVPacket avEncodedPacket;
av_init_packet(&avEncodedPacket);
avEncodedPacket.data = NULL;
avEncodedPacket.size = 0;
destAvFrame->pts = i;
avcodec_encode_video2(h264encoderContext, &avEncodedPacket,
destAvFrame, &got_frame);
if (got_frame) {
ShowErrorMessage(
"Encoded a frame of size \n",-1); //+ (string)avEncodedPacket.size + "\n");
if (fwrite(avEncodedPacket.data, 1, avEncodedPacket.size,
videoOutFile) < (unsigned) avEncodedPacket.size)
ShowErrorMessage(
"Could not write all \n",-1);
//+ avEncodedPacket.size
//+ " bytes, but will continue..\n"
fflush(videoOutFile);
}
/**
* Per-frame cleanup
*/
av_packet_free_side_data(&avEncodedPacket);
av_free_packet(&avEncodedPacket);
av_freep(sourceAvFrame->data);
av_frame_free(&sourceAvFrame);
av_freep(destAvFrame->data);
av_frame_free(&destAvFrame);
}
fwrite(endcode, 1, sizeof(endcode), videoOutFile);
fclose(videoOutFile);
/**
* Final cleanup
*/
avformat_free_context(cv2avFormatContext);
avcodec_close(h264encoderContext);
avcodec_free_context(&h264encoderContext);
} else if (command == "createFile") {
file_thread_.message_loop().PostWork(
callback_factory_.NewCallback(&RecorderInstance::Save,
file_name, file_text));
}
}
void OpenFileSystem(int32_t /* result */) {
int32_t rv = file_system_.Open(1024 * 1024, pp::BlockUntilComplete());
if (rv == PP_OK) {
file_system_ready_ = true;
// Notify the user interface that we're ready
ShowStatusMessage("STORAGE READY");
} else {
ShowErrorMessage("Failed to open file system", rv);
}
}
void Save(int32_t /* result */, const std::string& file_name,
const std::string& file_contents) {
if (!file_system_ready_) {
ShowErrorMessage("File system is not open", PP_ERROR_FAILED);
return;
}
pp::FileRef ref(file_system_, file_name.c_str());
pp::FileIO file(this);
int32_t open_result = file.Open(ref,
PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE
| PP_FILEOPENFLAG_TRUNCATE, pp::BlockUntilComplete());
if (open_result != PP_OK) {
ShowErrorMessage("File open for write failed", open_result);
return;
}
// We have truncated the file to 0 bytes. So we need only write if
// file_contents is non-empty.
if (!file_contents.empty()) {
if (file_contents.length() > INT32_MAX) {
ShowErrorMessage("File too big", PP_ERROR_FILETOOBIG);
return;
}
int64_t offset = 0;
int32_t bytes_written = 0;
do {
bytes_written = file.Write(offset,
file_contents.data() + offset, file_contents.length(),
pp::BlockUntilComplete());
if (bytes_written > 0) {
offset += bytes_written;
} else {
ShowErrorMessage("File write failed", bytes_written);
return;
}
} while (bytes_written
< static_cast(file_contents.length()));
}
// All bytes have been written, flush the write buffer to complete
int32_t flush_result = file.Flush(pp::BlockUntilComplete());
if (flush_result != PP_OK) {
ShowErrorMessage("File fail to flush", flush_result);
return;
}
ShowStatusMessage("Save success");
}
/// Encapsulates our simple javascript communication protocol
void ShowErrorMessage(const std::string& message, int32_t result) {
std::stringstream ss;
ss << "ERROR: " << message << " -- Error #: " << result << "\n";
PostMessage(ss.str());
}
void ShowStatusMessage(const std::string& message) {
std::stringstream ss;
ss << "LOG: " << message << "\n";
PostMessage(ss.str());
}
};
class RecorderModule: public pp::Module {
public:
RecorderModule() :
pp::Module() {
}
virtual ~RecorderModule() {
}
virtual pp::Instance* CreateInstance(PP_Instance instance) {
return new RecorderInstance(instance);
}
};
namespace pp {
/**
* This function is an entry point to a NaCl application.
* It must be implemented.
*/
Module* CreateModule() {
return new RecorderModule();
}
} // namespace pp
</recorderinstance></vector></sstream></iostream> -
How do I get videos to upload using carrierwave-video ?
10 juillet 2016, par EricI tried to follow the instructions on github to upload using carrierwave-video, but get an error that says the file or directory
mmpeg -i
doesn’t exist.The upload path for images is correct, just not the video one.
I added all of the following code necessary to help solve the error and minified as much as I possibly could.
This is the video uploader code using carrierwave :
class VideoUploader < CarrierWave::Uploader::Base
include CarrierWave::Video
storage :file
version :mp4 do
process :encode_video => [:mp4, resolution: "100x100"]
end
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
endThis is the movie controller code that handles uploading of videos :
class MoviesController < ApplicationController
include MoviesHelper
def index
mode "index"
end
def show
mode "show"
end
def new
mode "new"
end
def edit
mode "edit"
end
def create
mode "create"
end
def update
mode "update"
end
def destroy
mode "destroy"
end
def review
mode "review"
end
def approve
mode "approve"
end
def deny
mode "deny"
end
endThis is the model data for the movie that goes with it :
class Movie < ActiveRecord::Base
attr_accessible :created_on, :description, :maintenance, :reviewed, :subplaylist_id, :title, :user_id, :video, :remote_video_url
belongs_to :user
belongs_to :subplaylist
mount_uploader :video, VideoUploader
endThis is where the movie is supposed to be displayed but it is not working :
<% provide(:title, "Movie: Where movies are made!") %>
<% provide(:keywords, "movies, video") %>
<% provide(:description, "This is the place where users showcase their wonderful video talent.") %>
<p><%= notice %></p>
<h1 class="pageheader"><%= @movie.title %></h1>
<br />
<p class="pagetext"><%= video_tag(@movie.video_url.to_s, controls: true, class: "imagebox") %></p>
<p class="pagetext"><%= @movie.description %></p>
<p class="pagetext">Created on: <%= @movie.created_on.strftime("%B-%d-%Y") %></p>
<p class="pagetext">Owner: <%= getType(@movie.user) %><%= link_to @movie.user.vname, user_path(@movie.user) %></p>
<br />
<p class="pagetext"><%= link_to 'Back', mainplaylist_subplaylist_path(@subplaylist.mainplaylist, @movie.subplaylist) %></p>This is where the movie new action is :
<% provide(:title, "Movie: Create new movies here!") %>
<% provide(:description, "New movies are uploaded only to the site when the movie gets approved.") %>
<h1 class="pagetextheader">New movie</h1>
<%= render 'form' %>
<p class="pagetext"><%= link_to 'Back', mainplaylist_subplaylist_path(@subplaylist.mainplaylist, @subplaylist) %></p>This is where the movies forum parameters are :
<%= form_for([@subplaylist, @movie], :html=>{:multipart => true}) do |f| %>
<% if @movie.errors.any? %>
<div>
<h2><%= pluralize(@movie.errors.count, "error") %> prohibited this movie from being saved:</h2>
<ul>
<% @movie.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<br />
<div class="pagetext">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="pagetext">
<%= f.file_field :video %>
</div>
<div class="pagetext">
<%= f.label :remote_video_url, "or video URL" %><br />
<%= f.text_field :remote_video_url %>
</div>
<div class="pagetext">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
<div class="pagetext">
<%= f.submit %>
</div>
<br />
<% end %>This is the movies helper code :
module MoviesHelper
def mode(type)
code = auto_logout
if(code == true)
sign_out
redirect_to root_path
else
#Check if Maintenance is turned_on
allmode = Maintenancemode.find_by_id(1)
moviemode = Maintenancemode.find_by_id(19)
mode_turned_on = (allmode.maintenance_on || moviemode.maintenance_on)
#Determine if any maintenance is on
if(mode_turned_on)
#Determine if we are a regular user
regularUser = (!current_user || !current_user.admin?)
if(regularUser)
#Determine which maintenance mode is on
if(allmode.maintenance_on)
redirect_to maintenance_path
else
redirect_to movies_maintenance_path
end
else
switch type
end
else
switch type
end
end
end
private
def getType(user)
if(user.admin)
value = "$"
else
typeFound = Usertype.find_by_user_id(user.id)
if(typeFound)
type = typeFound.privilege
if(type == "Reviewer")
value = "^"
elsif(type == "Banned")
value = "!"
else
value = "~"
end
else
value = "~"
end
end
return value
end
def movieApproved
movieFound = Movie.find_by_id(params[:movie_id])
if(movieFound)
movieFound.reviewed = true
pouch = Pouch.find_by_user_id(movieFound.user_id)
pointsForMovie = 10
pouch.amount += pointsForMovie
@pouch = pouch
@pouch.save
@movie = movieFound
@movie.save
# MovieMailer.movie_approved(@movie, pointsForMovie).deliver
redirect_to movies_review_path
else
render "public/404"
end
end
def movieDenied
movieFound = Movie.find_by_id(params[:movie_id])
if(movieFound)
#Retrieve the user who owns this pet first
#userEmail = petFound.user.email
#Send mail to user with link to edit the pet they sent
@movie = movieFound
MovieMailer.movie_denied(@movie).deliver
redirect_to movies_review_path
else
render "public/404"
end
end
def createMovie(subplaylistFound)
newMovie = subplaylistFound.movies.new
@subplaylist = subplaylistFound
@movie = newMovie
end
def saveMovie(subplaylistFound, logged_in)
newMovie = subplaylistFound.movies.new(params[:movie])
newMovie.user_id = logged_in.id
currentTime = Time.now
newMovie.created_on = currentTime
@movie = newMovie
if(@movie.save)
@subplaylist = subplaylistFound
# MovieMailer.review_movie(@movie).deliver
flash[:success] = "#{@movie.title} is currently being reviewed please check back later."
redirect_to subplaylist_movie_path(@subplaylist, @movie)
else
render "new"
end
end
def switch(type)
if(type == "index") #Admin only
logged_in = current_user
if(logged_in)
if(logged_in.admin)
allMovies = Movies.order("created_on desc").page(params[:page]).per(10)
@movies = allMovies
else
redirect_to root_path
end
else
redirect_to root_path
end
elsif(type == "show")
movieFound = Movie.find_by_id(params[:id])
if(movieFound)
subplaylistFound = Subplaylist.find_by_id(params[:subplaylist_id])
if(subplaylistFound)
if(movieFound.reviewed)
@subplaylist = subplaylistFound
@movie = movieFound
else
logged_in = current_user
if(logged_in)
userMatch = ((logged_in.id == movieFound.user_id) || logged_in.admin)
if(userMatch)
@subplaylist = subplaylistFound
@movie = movieFound
else
redirect_to root_path
end
else
redirect_to root_path
end
end
else
redirect_to root_path
end
else
render "public/404"
end
elsif(type == "new")
logged_in = current_user
if(logged_in)
subplaylistFound = Subplaylist.find_by_id(params[:subplaylist_id])
if(subplaylistFound)
if(subplaylistFound.collab_mode)
createMovie(subplaylistFound)
else
userMatch = (logged_in.id == subplaylistFound.user_id)
if(userMatch)
createMovie(subplaylistFound)
else
redirect_to root_path
end
end
else
render "public/404"
end
else
redirect_to root_path
end
elsif(type == "create")
logged_in = current_user
if(logged_in)
subplaylistFound = Subplaylist.find_by_id(params[:subplaylist_id])
if(subplaylistFound)
if(subplaylistFound.collab_mode)
saveMovie(subplaylistFound, logged_in)
else
userMatch = (logged_in.id == subplaylistFound.user_id)
if(userMatch)
saveMovie(subplaylistFound, logged_in)
else
redirect_to root_path
end
end
else
render "public/404"
end
else
redirect_to root_path
end
elsif(type == "edit")
logged_in = current_user
if(logged_in)
movieFound = Movie.find_by_id(params[:id])
if(movieFound)
userMatch = (logged_in.id == movieFound.user_id)
if(userMatch)
subplaylistFound = Subplaylist.find_by_id(movieFound.subplaylist_id)
if(subplaylistFound)
@subplaylist = subplaylistFound
@movie = movieFound
else
render "public/404"
end
else
redirect_to root_path
end
else
render "public/404"
end
else
redirect_to root_path
end
elsif(type == "update")
logged_in = current_user
if(logged_in)
movieFound = Movie.find_by_id(params[:id])
if(movieFound)
userMatch = (logged_in.id == movieFound.user_id)
if(userMatch)
subplaylistFound = Subplaylist.find_by_id(movieFound.subplaylist_id)
if(subplaylistFound)
@movie = movieFound
if(@movie.update_attributes(params[:movie]))
@subplaylist = subplaylistFound
flash[:success] = 'Movie was successfully updated.'
redirect_to subplaylist_movie_path(@subplaylist, @movie)
else
render "edit"
end
else
render "public/404"
end
else
redirect_to root_path
end
else
render "public/404"
end
else
redirect_to root_path
end
elsif(type == "destroy")
logged_in = current_user
if(logged_in)
movieFound = Movie.find_by_id(params[:id]) #Need to move this below the admin section to protect it
if(movieFound)
if(logged_in.admin)
subplaylistFound = Subplaylist.find_by_id(movieFound.subplaylist_id)
if(subplaylistFound)
@movie = movieFound
@subplaylist = subplaylistFound
@movie.destroy
redirect_to mainplaylist_subplaylist_path(@subplaylist.mainplaylist, @subplaylist)
else
render "public/404"
end
else
redirect_to root_path
end
else
render "public/404"
end
else
redirect_to root_path
end
elsif(type == "review") #Admin
logged_in = current_user
if(logged_in)
if(logged_in.admin)
allMovies = Movie.all
moviesToReview = allMovies.select{|movie| !movie.reviewed}
@movies = Kaminari.paginate_array(moviesToReview).page(params[:page]).per(10)
else
typeFound = Usertype.find_by_user_id(logged_in.id)
if(typeFound.privilege == "Reviewer")
allMovies = Movie.all
moviesToReview = allMovies.select{|movie| !movie.reviewed}
@movies = Kaminari.paginate_array(moviesToReview).page(params[:page]).per(10)
else
redirect_to root_path
end
end
else
redirect_to root_path
end
elsif(type == "approve") #Admin
logged_in = current_user
if(logged_in)
if(logged_in.admin)
movieApproved
else
typeFound = Usertype.find_by_user_id(logged_in.id)
if(typeFound.privilege == "Reviewer")
movieApproved
else
redirect_to root_path
end
end
else
redirect_to root_path
end
elsif(type == "deny") #Admin
logged_in = current_user
if(logged_in)
if(logged_in.admin)
movieDenied
else
typeFound = Usertype.find_by_user_id(logged_in.id)
if(typeFound.privilege == "Reviewer")
movieDenied
else
redirect_to root_path
end
end
else
redirect_to root_path
end
end
end
endThis is the subplaylists show code :
<% provide(:title, "Subplaylist: The place where users videos gets uploaded to!") %>
<% provide(:keywords, "user, video, uploaded") %>
<% provide(:description, "Allows the categorization of various videos that the user submitted successfully.") %>
<p><%= notice %></p>
<h1 class="pageheader"><%= @subplaylist.title %></h1>
<br />
<p class="pagetext"><%= @subplaylist.description %></p>
<br />
<div class="pagebox"><%= paginate @movies %></div>
<br />
<div class="pagetext">
<% @movies.each_with_index do |movie, index| %>
<div class="container">
<div class="inner">
<div class="inner"><%= link_to movie.title, subplaylist_movie_path(@subplaylist, movie) %></div>
<% if current_user && (current_user.id == movie.user_id || current_user.admin? )%>
<div class="inner"><%= button_to 'Edit', edit_subplaylist_movie_path(@subplaylist, movie), method: :get %></div>
<div class="inner"><%= button_to 'Destroy', [@subplaylist, movie], method: :delete, data: { confirm: 'Are you sure?' } %></div>
<% end %>
<p><%= video_tag movie.video_url(:thumb).to_s, controls: true %></p>
</div>
<br />
<p>Created on: <%= movie.created_on.strftime("%B-%d-%Y") %></p>
<p>Owner: <%= getType(movie.user) %><%= link_to movie.user.vname, user_path(movie.user) %></p>
</div>
<% if ((index + 1) % 3) == 0 %>
<br />
<br />
<% end %>
<% end %>
</div>
<br />
<% if current_user %>
<p class="pagetext"><%= link_to "New Movie", new_subplaylist_movie_path(@subplaylist) %></p>
<br />
<% end %>
<p class="pagetext"><%= link_to 'Back', user_mainplaylist_path(@mainplaylist.user.vname, @subplaylist.mainplaylist.title) %></p>This is the subplaylists model :
class Subplaylist < ActiveRecord::Base
attr_accessible :title, :description, :collab_mode
belongs_to :user
belongs_to :mainplaylist
has_many :movies, :foreign_key => "subplaylist_id", :dependent => :destroy
VALID_NAME = /\A[A-Za-z][A-Za-z1-9][A-Za-z1-9 ]+\z/
validates :title, presence: true, format: {with: VALID_NAME}
validates :description, presence: true
endThis is the subplaylists controller code :
class SubplaylistsController < ApplicationController
include SubplaylistsHelper
def index
mode "index"
end
def show
mode "show"
end
def new
mode "new"
end
def edit
mode "edit"
end
def create
mode "create"
end
def update
mode "update"
end
def destroy
mode "destroy"
end
endThis is the subplaylist helper code :
module SubplaylistsHelper
def mode(type)
code = auto_logout
if(code == true)
sign_out
redirect_to root_path
else
#Check if Maintenance is turned_on
allmode = Maintenancemode.find_by_id(1)
subplaylistmode = Maintenancemode.find_by_id(18)
mode_turned_on = (allmode.maintenance_on || subplaylistmode.maintenance_on)
#Determine if any maintenance is on
if(mode_turned_on)
#Determine if we are a regular user
regularUser = (!current_user || !current_user.admin?)
if(regularUser)
#Determine which maintenance mode is on
if(allmode.maintenance_on)
redirect_to maintenance_path
else
redirect_to subplaylists_maintenance_path
end
else
switch type
end
else
switch type
end
end
end
private
def getType(user)
if(user.admin)
value = "$"
else
typeFound = Usertype.find_by_user_id(user.id)
if(typeFound)
type = typeFound.privilege
if(type == "Reviewer")
value = "^"
elsif(type == "Banned")
value = "!"
else
value = "~"
end
else
value = "~"
end
end
return value
end
def switch(type)
if(type == "show")
subplaylistFound = Subplaylist.find_by_id(params[:id])
if(subplaylistFound)
mainplaylistFound = Mainplaylist.find_by_title(params[:mainplaylist_id])
if(mainplaylistFound)
playlistMatch = (subplaylistFound.mainplaylist_id == mainplaylistFound.id)
if(playlistMatch)
@mainplaylist = mainplaylistFound
@subplaylist = subplaylistFound
subplaylistMovies = @subplaylist.movies.all
reviewedMovies = subplaylistMovies
if(subplaylistMovies.count > 0)
reviewedMovies = subplaylistMovies.select{|movie| movie.reviewed}
end
@movies = Kaminari.paginate_array(reviewedMovies).page(params[:page]).per(10)
else
redirect_to root_path
end
else
render "public/404"
end
else
redirect_to root_path
end
elsif(type == "destroy")
logged_in = current_user
if(logged_in)
subplaylistFound = Subplaylist.find_by_id(params[:id]) #Need to move this below the admin section to protect it
if(subplaylistFound)
if(logged_in.admin)
mainplaylistFound = Mainplaylist.find_by_id(subplaylistFound.mainplaylist_id)
if(mainplaylistFound)
@subplaylist = subplaylistFound
@mainplaylist = mainplaylistFound
@subplaylist.destroy
redirect_to mainplaylist_subplaylists_path(@mainplaylist)
else
render "public/404"
end
else
redirect_to root_path
end
else
render "public/404"
end
else
redirect_to root_path
end
end
end
endThis is the User model :
class User < ActiveRecord::Base
attr_accessible :email, :first_name, :last_name, :login_id, :vname, :password, :password_confirmation, :avatar
has_secure_password
mount_uploader :avatar, AvatarUploader
before_save { |user| user.email = user.email.downcase }
before_save { |user| user.first_name = user.first_name.humanize }
#key
has_one :sessionkey, :foreign_key => "user_id", :dependent => :destroy
has_one :usertype, :foreign_key => "user_id", :dependent => :destroy
#Video section
has_many :mainplaylists, :foreign_key => "user_id", :dependent => :destroy
has_many :subplaylists, :foreign_key => "user_id", :dependent => :destroy
has_many :movies, :foreign_key => "user_id", :dependent => :destroy
#validates :first_name, presence: true
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
VALID_NAME_REGEX = /\A[a-z][a-z][a-z]+\z/i
VALID_VNAME_REGEX = /\A[A-Za-z][A-Za-z][A-Za-z][A-Za-z0-9 ]+([-][A-Za-z0-9 ]+)?\z/
VALID_PASSWORD_REGEX = /\A[A-Za-z0-9!][A-Za-z0-9!][A-Za-z0-9!][A-Za-z0-9!][A-Za-z0-9!][A-Za-z0-9!]+\z/
validates :first_name, presence: true, format: { with: VALID_NAME_REGEX}
validates :last_name, presence: true, format: { with: VALID_NAME_REGEX}
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX}
validates :login_id, presence: true, format: { with: VALID_VNAME_REGEX}, uniqueness: { case_sensitive: false}
validates :vname, presence: true, format: { with: VALID_VNAME_REGEX}, uniqueness: { case_sensitive: false}
validates :password, length: {minimum: 6}#, format: { with: VALID_PASSWORD_REGEX}
validates :password_confirmation, presence: true #, format: { with: VALID_PASSWORD_REGEX}
def to_param
vname
end
endThis is the sessionkey model :
class Sessionkey < ActiveRecord::Base
belongs_to :user
endThis is the usertype model :
class Usertype < ActiveRecord::Base
attr_accessible :privilege, :user_id #Only priviledge will be changeable
belongs_to :user
endThis is the error message :
No such file or directory - ffmpeg -i /home/eric/Projects/Local/Lduelingpets/Trial/public/uploads/tmp/1466811951-3149-2702/mp4_TrialMovies.mp4
-
Undefined references while using ffmpeg 2.1.1 for Android
2 décembre 2013, par KernaldI'm building ffmpeg following the same pattern as halfninja's build : make the ffmpeg's
main
available from Java through JNI. I built ffmpeg with the following options :./configure \
--prefix=$PREFIX \
--disable-shared \
--enable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-doc \
--disable-symver \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=linux \
--arch=arm \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $ADDI_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS"$PREFIX
,TOOLCHAIN
, … being set to corresponding folders from my NDK.$ADDI_CFLAGS
is set to-marm
and$ADDI_LDFLAGS
and$ADDITIONAL_CONFIGURE_FLAGS
are both unset. The resulting static libraries are created :$ ls -1 android/arm/lib/ libavcodec.a libavdevice.a libavfilter.a libavformat.a libavutil.a libswresample.a libswscale.a pkgconfig
I expose them with an
Android.mk
file, ffmpeg being built in$NDK/sources/ffmpeg-2.1.1
:LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavdevice
LOCAL_SRC_FILES:= lib/libavdevice.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavcodec
LOCAL_SRC_FILES:= lib/libavcodec.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavformat
LOCAL_SRC_FILES:= lib/libavformat.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libswscale
LOCAL_SRC_FILES:= lib/libswscale.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavutil
LOCAL_SRC_FILES:= lib/libavutil.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavfilter
LOCAL_SRC_FILES:= lib/libavfilter.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libwsresample
LOCAL_SRC_FILES:= lib/libswresample.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)So, up to there, everything looks good. Now, I try to build the
ffmpeg
binary equivalent as a static library. I copied (and didn't change a single character for now)ffmpeg.c
,ffmpeg.h
,cmdutils.c
,cmdutils.h
,ffmpeg_opt.c
andffmpeg_filter.c
in myjni
folder. I also have two directly JNI-related files in this folder (copied from halfninja's build, I just changed the package name). Here's the relevantAndroid.mk
:LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := /Applications/android-ndk-r9b/sources/ffmpeg-2.1.1
LOCAL_CFLAGS := -Wdeprecated-declarations
LOCAL_MODULE := videokit
ANDROID_LIB := -landroid
LOCAL_LDLIBS += -llog -ljnigraphics -lz
LOCAL_SRC_FILES := videokit/com_rfc_video_ffmpeg_Videokit.c videokit/ffmpeg.c videokit/cmdutils.c videokit/ffmpeg_opt.c videokit/ffmpeg_filter.c
LOCAL_SHARED_LIBRARIES := libavdevice libavformat libavfilter libavcodec libwscale libavutil libswresample libswscale libpostproc
include $(BUILD_SHARED_LIBRARY)
$(call import-module,ffmpeg-2.1.1/android/arm)Everything compiles fine, but doesn't link. Here are the first errors :
[armeabi] SharedLibrary : libvideokit.so /Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld : ./obj/local/armeabi/objs/videokit/videokit/cmdutils.o : in function print_all_libs_info.constprop.5:jni/videokit/cmdutils.c:1063 : error : undefined reference to 'swresample_version' /Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld : ./obj/local/armeabi/objs/videokit/videokit/cmdutils.o : in function print_all_libs_info.constprop.5:jni/videokit/cmdutils.c:1063 : error : undefined reference to 'swresample_configuration' /Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld : ./obj/local/armeabi/objs/videokit/videokit/cmdutils.o : in function opt_default:jni/videokit/cmdutils.c:558 : error : undefined reference to 'swr_get_class' /Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld : ./obj/local/armeabi/objs/videokit/videokit/cmdutils.o : in function opt_default:jni/videokit/cmdutils.c:561 : error : undefined reference to 'swr_alloc' /Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld : ./obj/local/armeabi/objs/videokit/videokit/cmdutils.o : in function opt_default:jni/videokit/cmdutils.c:563 : error : undefined reference to 'swr_free' /Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld : ./obj/local/armeabi/objs/videokit/videokit/ffmpeg_opt.o : in function show_help_default:jni/videokit/ffmpeg_opt.c:2464 : error : undefined reference to 'swr_get_class'
What I don't understand is that these functions are defined and available in
libswresample.a
, which I'm linking to :arm-linux-androideabi-nm /Applications/android-ndk-r9b/sources/ffmpeg-2.1.1/android/arm/lib/libswresample.a | grep -i -e swr_get_class -e swresample_version 000001d4 T swr_get_class 00000178 T swresample_version
What am I doing wrong ? Is there another, maybe simpler way to expose ffmpeg as a static library available via JNI ? (I don't use halfninja's because I need at least ffmpeg 1.1, while his is in 0.9).